Ultimamente tem sido comum que vários sites, principalmente os relacionados a tecnologia, que antes possuíam apenas uma tema padrão, de cores claras, e que agora tem criado a possibilidade do usuário utilizar temas de cores escuras.
O StackOverflow lançou seu tema escuro no começo deste ano, e mais recentemente foi a vez do GitHub fazer o mesmo. Até a Google está testando um tema escuro para o seu buscador nos desktops.
Se você não tem tanta familiaridade com o desenvolvimento web, pode acabar pensando que é muito complexo criar um mecanismo de temas para manter um tema claro e um escuro da mesma forma que esses sites fazem.
Porém isso não é verdade! É possível criar um mecanismo de temas apenas utilizando JavaScript e CSS3 puros, sem nenhum outro framework ou ferramenta, e neste artigo eu vou mostrar como isso pode ser feito!
Variáveis, variáveis por todos os lados
Para começar, primeiro você deve entender exatamente o que vamos utilizar para criar o tema.
Primeiro, da parte de JavaScript, não temos muitos segredos, vamos apenas manipular alguns atributos para alterar o tema, e também iremos salvar a seleção do usuário no navegador, já vamos chegar nisso.
A mágica toda acontece com o CSS3, utilizando de suas variáveis.
As variáveis no CSS foram introduzidas na linguagem e podem ser usadas praticamente desde 2012, porém só a partir de 2015 que elas começaram a ser suportadas com maior abrangência pelos navegadores, e hoje praticamente só não é suportado pelo Internet Explorer (nem a Microsoft dá mais suporte para o IE...).
Como essas variáveis funcionam?
Em um arquivo CSS, as variáveis funcionam com um par de chave/valor, bem parecido como as propriedades dentro da regra de um seletor.
A diferença é que você pode definir qualquer nome para uma variável, e ela deve iniciar com dois traços.
Depois, para utilizar de fato a variável, basta utilizar var()
com o nome que foi definido.
Por exemplo, no código abaixo, é possível ver a utilização das variáveis para guardar valores de cores, tamanhos e medidas, etc. Qualquer valor que pode ser definido a uma propriedade, pode ser armazenada em uma variável, e depois elas podem ser reaproveitadas onde for necessário.
Você pode declarar as variáveis dentro de um seletor :root
ou html
, e assim elas estão disponíveis para serem utilizadas nas em todas as regras que você definir posteriormente.
:root { --fonte-padrao: 12px; --fonte-pequena: 8px; --fonte-grande: 16px; --cor-da-fonte: #12171a; --cor-de-alerta: #f10505; } .alerta { background-color: var(--cor-de-alerta); font-size: var(--fonte-grande); } #botao-enviar { color: var(--cor-da-fonte); font-size: var(--fonte-pequena); }
Mesmo sem levar em consideração a questão da criação de temas, o uso de variáveis no seu CSS já pode ser de grande valor. Centralizar em apenas um local os valores de cores e medidas diversas utilizadas deixa o código muito mais organizado e facilita a manutenção.
Agora que você já sabe o que são e como as variáveis do CSS podem ser utilizadas, vamos à criação dos nossos temas!
Come To The Dark Side
Para criação do nosso tema, vamos considerar que temos um site simples, composto de um index.html
para a página, um main.js
para o código JavaScript, e um style.css
para definir o estilo dessa nossa página.
Por exemplo, vamos imaginar que tenhamos essas regras no nosso style.css
:
body { background-color: #f5f5f5; margin: 0; font-family: "Roboto", sans-serif; color: #000000; } a { color: #0000ee; } .header-title { color: #333333; } .header-subtitle { color: #969696; } .page-header { padding: 15px; background-color: #e3e3e3; display: flex; flex-direction: column; align-items: center; justify-content: space-around; text-align: center; }
A primeira coisa que devemos fazer é pegar cada uma dessas cores que estão definidas entre as diversas regras do arquivo, transformar em variáveis, e adicionar em uma regra genérica para todo a tag html
da página.
Lembrando que você também pode fazer o mesmo com o valor de outras propriedades das regras, com as margens, espaçamentos, etc. Mas como o foco aqui é a criação do tema, vamos fazer isso apenas com as cores
html { --background-color: #f5f5f5; --header-background-color: #e3e3e3; --header-title-color: #333333; --header-subtitle-color: #969696; --link-color: #0000ee; --text-color: #000000; } body { background-color: var(--background-color); margin: 0; font-family: "Roboto", sans-serif; color: var(--text-color); } a { color: var(--link-color); } .header-title { color: var(--header-title-color); } .header-subtitle { color: var(--header-subtitle-color); } .page-header { padding: 15px; background-color: var(--header-background-color); display: flex; flex-direction: column; align-items: center; justify-content: space-around; text-align: center; }
Só de fazer essa alteração você já deixou seu CSS mais organizado, mantendo a página visualmente sem nenhuma alteração.
Agora o que nós precisamos fazer, é criar uma segunda regra com o conjunto de cores que serão utilizados no tema oposto. No caso, essas cores são do tema claro, então precisamos criar as mesmas variáveis para quando formos utilizar o tema escuro.
E para diferenciar entre os dois conjuntos de variáveis, em vez de manter as regras apenas para o seletor da tag html
, vamos definir também em conjunto uma propriedade data-theme
, que vai receber ou o valor light
quando for o tema claro, ou dark
quando for o tema escuro.
Veremos o uso dessa propriedade mais a frente.
html[data-theme="light"] { --background-color: #f5f5f5; --header-background-color: #e3e3e3; --header-title-color: #333333; --header-subtitle-color: #969696; --link-color: #0000ee; --divider-color: #006064; --text-color: #000000; } html[data-theme="dark"] { --background-color: #171e22; --header-background-color: #1c262b; --header-title-color: #5a7788; --header-subtitle-color: #35454f; --link-color: #7d95ff; --divider-color: #006435; --text-color: #acacac; } body { background-color: var(--background-color); margin: 0; font-family: "Roboto", sans-serif; color: var(--text-color); } a { color: var(--link-color); } .header-title { color: var(--header-title-color); } .header-subtitle { color: var(--header-subtitle-color); } .page-header { padding: 15px; background-color: var(--header-background-color); display: flex; flex-direction: column; align-items: center; justify-content: space-around; text-align: center; }
Agora, no nosso arquivo HTML, precisamos definir qual tema será utilizado por padrão, adicionando a propriedade data-theme
para a tag html
da página, com o valor desejado.
<html lang="en" data-theme="light"></html>
Só com isso você já vai conseguir ver o seu site alternando entre os dois temas criados, basta alterar o valor da propriedade data-theme
entre dark
e light
e recarregar a página que "magicamente" as cores serão alteradas!
Agora é ligar os pontos
Agora que nós temos as cores todas definidas como variáveis, e também já temos as cores do nossos dois temas, vamos precisar de um pouco de JavaScript para criar uma função que troque o valor do atributo data-theme
dinamicamente, permitindo que o usuário escolha o tema que achar mais agradável.
Na interface do usuário, isso pode ser feito de diversas maneiras: com uma caixa de seleção que liste os temas, um checkbox de ativação do tema, um botão que alterna entre claro e escuro, etc. Mas independente da maneira que for, o que deve ser feito internamente é definir na propriedade data-theme
o valor para o tema desejado.
Por exemplo, podemos criar uma função no JavaScript que, caso o tema atual seja o claro, ele alterne para o escuro, e vice-versa. E podemos vincular essa função no evento de clique de um botão que exista na página.
Toda vez que esse botão for clicado, a função irá obter o valor atual da propriedade data-theme
, e irá trocar para o valor inverso, e as cores serão alteradas.
É importante que apenas um elemento na página possua essa propriedade data-theme
, que usualmente é a tag html
ou a body
let themeToggler = document.getElementById("theme-toggler"); themeToggler.addEventListener("click", () => { let targetTheme; let currentTheme = document.documentElement.getAttribute("data-theme"); if (currentTheme === "light") { targetTheme = "dark"; } else { targetTheme = "light"; } document.documentElement.setAttribute("data-theme", targetTheme); });
Refletindo o tema do navegador
Todos os navegadores modernos, como o Chrome, Firefox e o Edge (o novo Edge, não o antigo) também possuem temas claros e escuros neles próprios, e é possível adicionar na nossa página uma função JavaScript que irá tentar obter essa configuração, e a sua página automaticamente ficará com o mesmo tema do navegador.
Essa função pode ser executada cada vez que a página é carregada, e deve buscar pela configuração prefers-color-scheme
no navegador.
Se essa configuração existir e o valor for dark
, definimos esse mesmo valor no nosso atributo data-theme
.
Agora, se a configuração for qualquer outra, ou se por um acaso o navegador não tiver suporte para ela e ela não existir, definimos nosso tema como light
, que é nosso tema padrão.
let browserTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; document.documentElement.setAttribute("data-theme", browserTheme);
Caso você deseje manter o tema escuro como padrão, é só inverter a verificação.
let browserTheme = window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
Salvando a seleção do usuário
Podemos também criar uma forma simples de salvar o tema selecionado pelo usuário, mantendo essa informação no localStorage
do navegador.
Desta forma você pode manter entre as seções do usuário o tema de preferência dele.
Para isso, na função de troca do tema, sempre que você alterar o atributo data-theme
, você pode também salvar o valor nolocalStorage
.
localStorage.setItem("theme", targetTheme);
Com essa informação salva, você pode fazer a chamada para uma outra função no carregamento da página para verificar se existe esse valor armazenado naquele navegador, e se existir, utilizá-lo. Caso contrário, fica definido o tema padrão.
let savedTheme = localStorage.getItem("theme"); if (savedTheme) { document.documentElement.setAttribute("data-theme", savedTheme); }
É possível até juntar na lógica a verificação tanto do tema salvo pelo usuário, quanto fazer refletir o tema do navegador.
Se existir um tema salvo, utiliza este. Caso contrário, tenta obter o tema configurado no navegador. Se o navegador não suportar, vai ficar definido o tema padrão.
let savedTheme = localStorage.getItem("theme"); if (savedTheme) { document.documentElement.setAttribute("data-theme", savedTheme); } else { let browserTheme = window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark"; document.documentElement.setAttribute("data-theme", browserTheme); }
Não se limite aos temas
Com esse mecanismo é possível criar quantos temas forem necessários, basta criar o conjunto de variáveis com os valores das cores de cada tema, e fazer as funções que atualizem o atributo data-theme
.
E também, é claro, as variáveis no CSS são excelentes para deixar o código mais organizado e centralizar as definições em apenas em um local mesmo que você não queira criar nenhum tema, funcionando muito bem também com frameworks de SPA, como o React e o Angular por exemplo, garantindo que todos os componentes sigam os mesmos padrões.
Caso deseje ver um exemplo de implementação desse mecanismo de temas, você pode consultar este repositório do GitHub: https://github.com/lfrigodesouza/dark-theme-with-css
Também pode ver ele em funcionamento nesta página: https://lfrigodesouza.github.io/dark-theme-with-css/
Top comments (0)