Skip to content
Advertisement

Adding a theme (one of three themes) when you switch, and a mode (dark or light) when you toggle, to a HTML element in pure JavaScript?

I am going to generate from Markdowm to a single offline HTML page with inline styles and inline scripts. It has a selection list of three themes, using :root and a toggle of dark or light modes, with classes .vscode-dark and .vscode-light, based on VSCode’s Markdowm Preview.

<p> Choose one theme</p>
<select name="theme-select" id="theme-select">
  <option value="voxel-theme-empresas">empresas</option>
  <option value="voxel-theme-ion">ion</option>
  <option value="voxel-theme-iti">iti</option>
</select>

<button onclick="switchMode()">Toggle dark or light mode</button>

<script>
function switchMode() {
   var element = document.body;
   element.classList.toggle("vscode-dark");
}
</script>

It should be like:

<body class="voxel-theme-empresas vscode-light">

# Teste 2

Nostrud nostrud excepteur mollit anim. Sint proident officia anim eu pariatur laboris excepteur amet Lorem Lorem commodo consequat ullamco. Pariatur aute ut aliqua aliquip consectetur ea.

</body>

<body class="voxel-theme-empresas vscode-dark">

# Teste 2

Nostrud nostrud excepteur mollit anim. Sint proident officia anim eu pariatur laboris excepteur amet Lorem Lorem commodo consequat ullamco. Pariatur aute ut aliqua aliquip consectetur ea.

</body>

<body class="voxel-theme-iti vscode-light">

# Teste 2

Nostrud nostrud excepteur mollit anim. Sint proident officia anim eu pariatur laboris excepteur amet Lorem Lorem commodo consequat ullamco. Pariatur aute ut aliqua aliquip consectetur ea.

</body>

<body class="voxel-theme-iti vscode-dark">

# Teste 2

Nostrud nostrud excepteur mollit anim. Sint proident officia anim eu pariatur laboris excepteur amet Lorem Lorem commodo consequat ullamco. Pariatur aute ut aliqua aliquip consectetur ea.

</body>

And CSS:

:root[class*=voxel-theme-empresas], :root:not([class^=voxel-theme-])
{
  --ids_color_action_primary_base: #ec7000;
  --ids_color_darktBg_base: #001e4f;
  --ids_color_lightBg_base: #fde9d7;
}

:root[class*=voxel-theme-ion], :root:not([class^=voxel-theme-])
{
  --ids_color_action_primary_base: #a7ce2e;
  --ids_color_darktBg_base: #133134;
  --ids_color_lightBg_base: #efface;
}

:root[class*=voxel-theme-iti], :root:not([class^=voxel-theme-])
{
  --ids_color_action_primary_base: #fe3386;
  --ids_color_darktBg_base: #2b374a;
  --ids_color_lightBg_base: #fcefef;
}

body
{
  font-size: large;
}

h1
{
  color: var(--ids_color_action_primary_base);
}

.vscode-light
{
  background-color: var(--ids_color_lightBg_base);
  color: var(--ids_color_darktBg_base);
}

.vscode-dark
{
  background-color: var(--ids_color_darktBg_base);
  color: var(--ids_color_lightBg_base);
}

Important observation

The root element classes have to remain preserved. I know it will not work if you try to add the class voxel-theme-empresas to body or div because it will trigger voxel-theme-iti‘s colour instead.

Advertisement

Answer

Try this simple solution to switch between themes.

// Initial elements
const select = document.getElementById('theme-select');
const button = document.getElementById('dark-mode');
const body = document.body;

const h1 = document.querySelector('h1');

const LIGHT = 'vscode-light';
const DARK = 'vscode-dark';

// Selection handler
select.addEventListener('change', event => {
  // We take a second class to use it later
  const classVScode = body.className.split(' ')[1];

  h1.textContent = event.target.value;
  // If the body has no current value (class)
  if (!body.classList.contains(event.target.value)) {
    // Making new styles
    body.className = `${event.target.value} ${classVScode}`;
  }
});

// Switch handler
button.addEventListener('click', () => {
  // We take a first class to use it later
  const classVoxel = body.className.split(' ')[0];
  // If body has a 'vscode-dark' class
  if (body.classList.contains(DARK)) {
    // Making new styles
    body.className = `${classVoxel} ${LIGHT}`;
    // Set attribute 'data' with theme
    body.setAttribute('data-vscode-theme-kind', `${LIGHT}`);
  } else {
    body.className = `${classVoxel} ${DARK}`;
    body.setAttribute('data-vscode-theme-kind', `${DARK}`);
  }
});
.voxel-theme-empresas,
:root:not([class^='voxel-theme-']) {
  --ids_color_action_primary_base: #ec7000;
  --ids_color_darktBg_base: #001e4f;
  --ids_color_lightBg_base: #fde9d7;
}

.voxel-theme-ion,
:root:not([class^='voxel-theme-']) {
  --ids_color_action_primary_base: #a7ce2e;
  --ids_color_darktBg_base: #133134;
  --ids_color_lightBg_base: #efface;
}

.voxel-theme-iti,
:root:not([class^='voxel-theme-']) {
  --ids_color_action_primary_base: #fe3386;
  --ids_color_darktBg_base: #2b374a;
  --ids_color_lightBg_base: #fcefef;
}

body {
  font-size: large;
}

h1 {
  color: var(--ids_color_action_primary_base);
}

.vscode-light {
  background-color: var(--ids_color_lightBg_base);
  color: var(--ids_color_darktBg_base);
}

.vscode-dark {
  background-color: var(--ids_color_darktBg_base);
  color: var(--ids_color_lightBg_base);
}
<body class="voxel-theme-empresas vscode-dark" data-vscode-theme-kind="vscode-dark">
  <p>Choose one theme</p>
  <h1>voxel-theme-empresas</h1>
  <select name="theme-select" id="theme-select">
    <option value="voxel-theme-empresas">empresas</option>
    <option value="voxel-theme-ion">ion</option>
    <option value="voxel-theme-iti">iti</option>
  </select>

  <button id="dark-mode">Toggle dark or light mode</button>
</body>
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement