Skip to Content
←Todas las publicaciones

Modo oscuro sin parpadeo

 — #Temas#Modo Oscuro

Botón de modo oscuro sin el parpadeo del tema por defecto. Las claves:

  • Variables CSS para el color del tema
  • Pon el atributo data-theme en <html>, no en <body>, para poder ejecutar el JS antes de que el DOM termine de renderizar
  • Ejecuta la comprobación de localStorage dentro del <head>
  • El JS del botón (manejador del clic) puede ir después del render

HTML

<!DOCTYPE html>
<html lang="es" data-theme="light">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    ...
    <script>
      // Si hay un tema guardado en localStorage, aplícalo al <html>
      const localStorageTheme = localStorage.getItem('theme');
      if (localStorageTheme) {
        document.documentElement.setAttribute('data-theme', localStorageTheme);
      }
    </script>
  </head>
  <body>
    <div class="theme-toggle">
      <button
        class="theme-toggle-btn js-theme-toggle"
        aria-label="Activar modo oscuro"
        title="Activar modo oscuro"
      >
        <!--
        <svg class="light-mode">
          <use xlink:href="#sun"></use>
        </svg>
        <svg class="dark-mode">
          <use xlink:href="#moon"></use>
        </svg>
        -->
      </button>
    </div>

    <script src="app.js"></script>
  </body>
</html>

Variables CSS

:root {
  --bg: #ffffff;
  --text: #000000;
}

[data-theme='dark'] {
  --bg: #000000;
  --text: #ffffff;
}

JavaScript

app.js
const themeToggleBtn = document.querySelector('.js-theme-toggle');

themeToggleBtn.addEventListener('click', () => onToggleClick());

const onToggleClick = () => {
  const { theme } = document.documentElement.dataset;
  const themeTo = theme && theme === 'light' ? 'dark' : 'light';
  const label = `Activar modo ${themeTo === 'dark' ? 'claro' : 'oscuro'}`;

  document.documentElement.setAttribute('data-theme', themeTo);
  localStorage.setItem('theme', themeTo);

  themeToggleBtn.setAttribute('aria-label', label);
  themeToggleBtn.setAttribute('title', label);
};

Recursos