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)