AqGoEs.
Desenvolvimento Web

Como Criar Dark Mode e Menu Mobile com JavaScript Puro e Tailwind

01/09/2026 Atualizado em 04/09/2026 4 min de leitura
Alan Queirós
Conteúdo por: Alan Queirós
AqGoEs
Compartilhe:
Resumir este post com: 💬 ChatGPT 🔍 Perplexity

📌 Navegue por tópicos

No artigo anterior, vimos como estruturar o visual HTML e Tailwind CSS do header do AqGoEs DeV. No entanto, um layout limpo só cumpre seu papel se a experiência do usuário for fluida.

Nesta etapa, vamos adicionar a camada de comportamento (interatividade) com JavaScript puro (Vanilla JS). Vamos resolver dois problemas vitais de front-end: o evento de clique do menu hambúrguer no celular e a navegação em Modo Escuro/Claro persistida no navegador do usuário.

Por que Usar LocalStorage para o Tema?

Quando um usuário escolhe o tema escuro em um site, ele espera que essa preferência seja mantida ao navegar entre as páginas ou ao retornar no dia seguinte.

A API de localStorage do navegador permite salvar pares de chave-valor diretamente no dispositivo do leitor. Isso evita o incômodo efeito de “tela piscando” (FOUC — Flash of Unstyled Content) no momento em que a página recarrega.

Código JavaScript Completo do Header

Abaixo está o script estruturado para manipular exatamente os elementos do nosso HTML:

document.addEventListener('DOMContentLoaded', () => {
  // --- 1. ELEMENTOS DO DOM ---
  const themeToggleBtn = document.getElementById('theme-toggle');
  const lightIcon = document.getElementById('theme-toggle-light-icon');
  const darkIcon = document.getElementById('theme-toggle-dark-icon');
  
  const menuToggleBtn = document.getElementById('menu-toggle');
  const mobileMenu = document.getElementById('mobile-menu');

  // --- 2. LÓGICA DO TEMA (DARK / LIGHT) ---
  const applyTheme = (isDark) => {
    if (isDark) {
      document.documentElement.classList.add('dark');
      lightIcon.classList.remove('hidden');
      darkIcon.classList.add('hidden');
    } else {
      document.documentElement.classList.remove('dark');
      lightIcon.classList.add('hidden');
      darkIcon.classList.remove('hidden');
    }
  };

  // Verifica a preferência salva ou o padrão do sistema operacional
  const savedTheme = localStorage.getItem('theme');
  const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
  
  const initialIsDark = savedTheme ? savedTheme === 'dark' : systemPrefersDark;
  applyTheme(initialIsDark);

  // Evento de clique para trocar o tema
  themeToggleBtn.addEventListener('click', () => {
    const isCurrentlyDark = document.documentElement.classList.contains('dark');
    const newThemeIsDark = !isCurrentlyDark;
    
    applyTheme(newThemeIsDark);
    localStorage.setItem('theme', newThemeIsDark ? 'dark' : 'light');
  });

  // --- 3. LÓGICA DO MENU MOBILE ---
  menuToggleBtn.addEventListener('click', () => {
    mobileMenu.classList.toggle('hidden');
  });
});

Entendendo a Lógica Passo a Passo

Para garantir que a implementação seja clara, analisaremos os blocos de código principais:

FuncionalidadeMétodos/PropriedadesO que faz na prática
O que faz na práticalocalStorage.getItem('theme')Lê do navegador se o usuário já salvou o tema no passado.
Preferência do Sistemawindow.matchMedia('(prefers-color-scheme: dark)')Se não houver nada salvo, detecta se o celular/PC do usuário já usa modo escuro.
Troca de Ícones.classList.toggle('hidden')Alterna a visibilidade do Sol e da Lua sem usar bibliotecas externas.
Menu HambúrguermobileMenu.classList.toggle('hidden')Exibe ou esconde o dropdown ao clicar no botão no celular.

Destaques de Execução Técnica

💡 Dica de Ouro: Coloque o trecho que verifica a preferência do tema no <head> do seu HTML (ou execute antes do carregamento do body). Isso garante que a classe dark seja injetada na tag <html> antes mesmo da renderização visual, eliminando completamente a piscada de luz ao trocar de página.

O Poder do matchMedia

Muitos desenvolvedores esquecem que o usuário já configurou o próprio sistema operacional com seu tema preferido. Ao usar window.matchMedia, seu blog respeita a escolha global do usuário logo no primeiro acesso.

Código Enxerto e Performático

Não utilizamos bibliotecas pesadas de terceiros para controlar a lógica da página. Com menos de 50 linhas de JavaScript puro, garantimos máxima velocidade de carregamento e pontuação alta no Google Lighthouse.

Conclusão

Com este script, o header do projeto AqGoEs DeV passa a ser interativo, acessível e otimizado para a experiência do usuário em qualquer tipo de tela ou momento do dia.

💡 Veja também

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *