preferências de light e dark do usuário

douglasabnovato
10 min readAug 7, 2022

Quero aplicar o estilo padrão de modo escuro de forma eficiente na minha aplicação. Pesquisar maneira de persistir as preferências do usuário, consultar o sistema usado e qualquer outra maneira de tornar a usabilidade ainda mais satisfatória.

Umas das funcionalidades que está na moda em Blogs e Sites é o Dark Mode. Devs, em sua maioria, curtem bastante utilizar temas escuros, tanto na IDE quanto em outros apps.

Vamos mostrar como adicionar Dark Mode no Blog de maneira rápida e fácil, sem depender do JavaScript, usando apenas o CSS.

Vou trazer um conceito — uma ideia — que vai além de mudar o background do fundo da tela e as cores dos textos, que é o padrão. Vamos escurecer um pouco as imagens também.

O usuário quer ler um conteúdo com tema escuro, então a imagem do conteúdo precisa se adequar e ter menos brilho.

Os navegadores modernos trazem a opção de configurar a aparência para dark 🌑 light 🌕 ou seguir as preferências já definidas no tema que o usuário escolheu no Sistema Operacional. 🌗

Configurando a aparência do Navegador Brave para Dark Theme

🍥 CSS @Media Screen — prefers-color-scheme

Quem nos ajuda com essa funcionalidade no CSS é a incrível media query com prefers-color-scheme.

<style>

/* Base (light mode) styles */

@media screen and (prefers-color-scheme: dark) { /* Dark mode styles */ }

</style>

Com prefers-color-scheme detectamos se o usuário está usando o tema de cores escuras (dark) ou claras (light).

💪 Praticando

Neste post construímos um blog com NextJS. Agora vamos adicionar a funcionalidade Dark Mode utilizando a técnica que mencionei acima.

Link para o código fonte.

No arquivo styles/index.css adicionamos algumas propriedades CSS para estilizar alguns elementos HTML.

Por padrão, as cores seguirão o tema claro (Light Theme) e, se o usuário estiver com o Dark Theme configurado no Navegador ou sistema Operacional, ele será aplicado.

🖼️ Imagem em Dark Mode

Uma sugestão seria tirar um pouco do brilho da imagem, conforme foi feito na tag img:

img { filter: brightness(0.9); }

Veja como usar o filtro na imagem. Com Dark Theme há uma boa diferença:

Comparação com brilho padrão da imagem e diminuindo o brilho da imagem no Dark Mode.

💡 Outra ideia seria ter a imagens com SVG, dessa forma poderia customiza-las facilmente com JavaScript ou CSS. Alterando o fundo da imagem na propriedade fill do arquivo SVG.

🥂 Confira o Resultado final

👉 Link do Blog no ar.

👊 Conclusão

Sem nenhum código JavaScript e com pouquíssimas linhas de CSS adicionamos Dark Mode no Blog. Ficou bem legal e acabou ficando automático — seguindo a sugestão do navegador ou do sistema operacional do usuário.

Poderia ter um botão switch para usuário trocar o tema:

Mas aqui o objetivo dessa vez foi fazer da maneira mais rápida e simples, usando apenas o CSS.

🔥 Fica de desafio colocar esse botão.

Dá para trocar o ícones do favicon usando apenas CSS também. Fica aqui a sugestão de leitura nos links abaixo:

🔗 Links

Para aperfeiçoar essa prática citada acima, vamos a um artigo no web.dev.

A propriedade CSS color-scheme e a metatag correspondente permitem que os desenvolvedores optem por suas páginas nos padrões específicos do tema da folha de estilo do agente do usuário.

O recurso de preferência de mídia do usuário com prefers-color-scheme

O prefers-color-scheme preferenciais oferece aos desenvolvedores controle total sobre a aparência de suas páginas. Se você não estiver familiarizado com ele, leia meu artigo prefers-color-scheme : Olá escuridão, minha velha amiga , onde documentei tudo o que sei sobre a criação de incríveis experiências no modo escuro.

Uma peça do quebra-cabeça que foi mencionada apenas brevemente no artigo é a color-scheme e a metatag correspondente com o mesmo nome. Ambos tornam a sua vida como desenvolvedor mais fácil, permitindo que você opte pela sua página em padrões específicos do tema da folha de estilo do agente do usuário, como, por exemplo, controles de formulário, barras de rolagem, bem como sistema de cores do CSS. Ao mesmo tempo, esse recurso impede que os navegadores apliquem quaisquer transformações por conta própria.

A folha de estilo do agente do usuário

Antes de continuar, deixe-me descrever brevemente o que é uma folha de estilo do agente do usuário. Na maioria das vezes, você pode pensar na palavra agente do usuário (UA) como uma forma sofisticada de dizer navegador .

A folha de estilo UA determina a aparência padrão de uma página. Como o nome sugere, uma folha de estilo do UA é algo que depende do UA em questão. Você pode dar uma olhada na folha de estilo UA do Chrome (e do Chromium) e compará-la com a do Firefox ou Safari (e do WebKit).

Normalmente, as folhas de estilo UA concordam com a maioria das coisas. Por exemplo, todos eles tornam os links em azul, o texto geral em preto e a cor de fundo em branco, mas também existem diferenças importantes (e às vezes irritantes), por exemplo, como eles estilizam os controles de formulário.

Dê uma olhada mais de perto na folha de estilo UA do WebKit e o que ela faz em relação ao modo escuro. (Faça uma pesquisa de texto completo por “escuro” na folha de estilo.) O padrão fornecido pela folha de estilo muda com base no modo escuro estar ativado ou desativado.

Para ilustrar isso, aqui está uma regra CSS usando a pseudo classe :matches e as variáveis internas do WebKit como -apple-system-control-background , bem como a diretiva do pré-processador interno do WebKit #if defined:

Você notará alguns valores fora do padrão para as propriedades color e background-color acima. Nem text nem -apple-system-control-background são cores CSS válidas. São cores semânticas internas do WebKit.

Acontece que o CSS padronizou as cores do sistema semântico. Eles são especificados no módulo de cores CSS nível 4 . Por exemplo, Canvas (não deve ser confundido com a tag <canvas> ) é para o fundo do conteúdo do aplicativo ou documentos, enquanto CanvasText é para texto no conteúdo do aplicativo ou documentos. Os dois andam juntos e não devem ser usados isoladamente.

As folhas de estilo do UA podem usar suas próprias cores proprietárias ou as cores do sistema semântico padronizado para determinar como os elementos HTML devem ser renderizados por padrão. Se o sistema operacional estiver definido para o modo escuro ou usar um tema escuro, CanvasText (ou text ) seria condicionalmente definido como branco e Canvas (ou -apple-system-control-background ) seria definido como preto. A folha de estilo UA atribui o seguinte CSS apenas uma vez e cobre os modos claro e escuro.

A propriedade color-scheme do CSS

A especificação CSS Módulo do Ajuste de Cores Nível 1 apresenta um modelo e controla o ajuste automático de cores pelo agente do usuário com o objetivo de lidar com as preferências do usuário, como modo escuro, ajuste de contraste ou esquemas específicos de cores desejados.

A color-scheme definida nele permite que um elemento indique com quais esquemas de cores ele se sente confortável para ser renderizado. Esses valores são negociados com as preferências do usuário, resultando em um esquema de cores escolhido que afeta coisas da interface do usuário (IU), como as cores padrão dos controles de formulário e barras de rolagem, bem como os valores usados das cores do sistema CSS. Os seguintes valores são atualmente suportados:

  • normal Indica que o elemento não tem conhecimento dos esquemas de cores e, portanto, o elemento deve ser renderizado com o esquema de cores padrão do navegador.
  • [ light | dark ]+ Indica que o elemento está ciente e pode lidar com os esquemas de cores listados e expressa uma preferência ordenada entre eles.

O fornecimento de ambas as palavras-chave indica que o primeiro esquema é o preferido (pelo autor), mas o segundo também é aceitável se o usuário preferir.

Nesta lista, light representa um esquema de cores claras, com cores de fundo claras e cores de primeiro plano escuras, enquanto que dark representa o oposto, com cores de fundo escuras e cores de primeiro plano claras.

Para todos os elementos, a renderização com um esquema de cores deve fazer com que as cores usadas em todas as IUs fornecidas pelo navegador para o elemento correspondam à intenção do esquema de cores. Os exemplos são barras de rolagem, sublinhados de verificação ortográfica, controles de formulário, etc.

A color-scheme pode ser usada no nível :root , bem como em um nível individual por elemento.

No :root , a renderização com um esquema de cores deve afetar adicionalmente a cor da superfície da tela (ou seja, a cor de fundo global), o valor inicial da propriedade color e os valores usados das cores do sistema, e também deve afetar as barras de rolagem da janela de visualização.

A metatag color-scheme

Honrar a color-scheme requer que o CSS seja primeiro baixado (se for referenciado por meio de <link rel="stylesheet"> ) e analisado. Para ajudar os agentes do usuário a renderizar o plano de fundo da página com o esquema de cores desejado imediatamente, um valor para color-scheme também pode ser fornecido em um elemento <meta name="color-scheme"> .

Combinando color-scheme e prefers-color-scheme

Como a metatag e a propriedade CSS (se aplicada ao :root ) eventualmente resultam no mesmo comportamento, sempre recomendo especificar o esquema de cores por meio da metatag, para que o navegador possa adotar o esquema preferido mais rapidamente.

Embora para páginas de linha de base absolutas nenhuma regra CSS adicional seja necessária, no caso geral você deve sempre combinar o color-scheme com prefers-color-scheme. Por exemplo, o WebKit CSS color -webkit-link proprietário, usado pelo WebKit e Chrome para o link clássico azul rgb(0,0,238), tem uma relação de contraste insuficiente de 2,23:1 em um fundo preto e falha tanto no WCAG AA quanto bem como os requisitos WCAG AAA.

Eu abri bugs para Chrome , WebKit e Firefox , bem como um meta issue no padrão HTML para consertar isso.

Interação com prefers-color-scheme

A interação da color-scheme e da metatag correspondente com o recurso de preferência de mídia do usuário prefers-color-scheme pode parecer confuso a primeira vista.

Na verdade, eles jogam muito bem juntos. A coisa mais importante a entender é que o color-scheme determina exclusivamente a aparência padrão, ao passo que o prefers-color-scheme determina a aparência estilizável. Para tornar isso mais claro, assuma a seguinte página:

O código CSS embutido na página define o elemento <fieldset> de background-color para gainsboro no caso geral, e darkslategray se o usuário prefere um esquema de cores dark de acordo com as prefers-color-scheme preferências de mídia do usuário.

Por meio do elemento <meta name="color-scheme" content="dark light"> , a página informa ao navegador que oferece suporte para um tema escuro e um claro, com preferência por um tema escuro.

Dependendo se o sistema operacional está definido para o modo escuro ou claro, a página inteira aparece claro no escuro, ou vice-versa, com base na folha de estilo do agente do usuário. Não CSS adicional fornecido pelo desenvolvedor envolvido para alterar o texto do parágrafo ou a cor de fundo da página.

Observe como a background-color de fundo do elemento <fieldset> muda com base na habilitação do modo escuro, seguindo as regras da folha de estilo embutida fornecida pelo desenvolvedor na página. Ou é gainsboro ou darkslategray.

Modo claro: estilos especificados pelo desenvolvedor e pelo agente do usuário. O texto é preto e o fundo é branco de acordo com a folha de estilo do agente do usuário. A background-color de fundo do elemento <fieldset> é gainsboro de acordo com a folha de estilo do desenvolvedor embutida.
Modo escuro: estilos especificados pelo desenvolvedor e pelo agente do usuário. O texto é branco e o fundo é preto de acordo com a folha de estilo do agente do usuário. A background-color de fundo do elemento <fieldset> é darkslategray de acordo com a folha de estilo do desenvolvedor embutida.

A aparência do elemento <button> é controlada pela folha de estilo do agente do usuário. Sua color é definida para a cor do sistema ButtonText background-color e as quatro border-color são definidas para a cor do sistema ButtonFace.

Modo de luz: A background-color e as várias border-color são definidas para a cor do sistema ButtonFace.

Agora observe como a border-color do elemento <button> muda. O valor calculado para as border-top-color e border-bottom-color muda de rgba(0, 0, 0, 0.847) (enegrecido) para rgba(255, 255, 255, 0.847) (esbranquiçado), desde que o usuário do agente atualiza o ButtonFace dinamicamente com base no esquema de cores. O mesmo se aplica à color do elemento <button> que é definido para a cor do sistema correspondente ButtonText .

Modo claro: Os valores calculados de border-top-color e border-bottom-color que são definidos como ButtonFace na folha de estilo do agente do usuário agora são rgba(0, 0, 0, 0.847).
Modo escuro: Os valores calculados de border-top-color e border-bottom-color que são definidos como ButtonFace na folha de estilo do agente do usuário agora são rgba(255, 255, 255, 0.847).

demo

Você pode ver os efeitos do color-scheme de cores aplicado a um grande número de elementos HTML em uma demonstração no Glitch . A demonstração mostra deliberadamente a violação WCAG AA e WCAG AAA com as cores de link mencionadas no aviso acima .

A demonstração mudou para color-scheme: light.
A demonstração mudou para o color-scheme: dark. Observe a violação WCAG AA e WCAG AAA com as cores do link.

Reconhecimentos

A color-scheme e a metatag correspondente foram implementadas por Rune Lillesveen . Rune também é um co-editor da especificação CSS Color Adjustment Module Nível 1. Imagem do herói por Philippe Leone no Unsplash .

Utilizei as informações desse artigo para fazer os modos dark e light de algumas aplicações frontend que estou no meu perfil do github. Espero que tenham gostado. Deixe o seu aplauso e até o próximo artigo.

--

--