Melhoria no estilo padrão do modo escuro com a propriedade CSS do esquema de cores e a metatag correspondente

A propriedade CSS color-scheme e a metatag correspondente permitem que os desenvolvedores ativem as páginas para os padrões específicos do tema da folha de estilo do user agent.

Contexto

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

O recurso de mídia de preferência do usuário prefers-color-scheme oferece aos desenvolvedores controle total sobre a aparência das páginas. Se você não tem familiaridade com isso, leia este artigo prefers-color-scheme: Olá, escuridão, meu velho amigo, em que documentei tudo o que sei sobre como criar experiências incríveis no modo escuro.

Uma peça de quebra-cabeça que foi mencionada brevemente no artigo é a propriedade CSS color-scheme e a metatag correspondente com o mesmo nome. Ambos facilitam sua vida como desenvolvedor, permitindo que você ative padrões específicos do tema da folha de estilo do user agent, como controles de formulário, barras de rolagem e cores do sistema CSS. Ao mesmo tempo, esse recurso impede que os navegadores apliquem transformações por conta própria.

Suporte ao navegador

prefers-color-scheme

Compatibilidade com navegadores

  • 76
  • 79
  • 67
  • 12.1

Origem

color-scheme

Compatibilidade com navegadores

  • 81
  • 81
  • 96
  • 13

Origem

A folha de estilo do user agent

Antes de continuar, vou descrever brevemente o que é uma folha de estilo de user agent. Na maioria das vezes, a palavra user agent (UA) é uma maneira sofisticada de dizer navegador. A folha de estilo do 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 analisar a folha de estilo UA do Chrome (e do Chromium) e compará-la com a do Firefox ou do Safari (e do WebKit). Normalmente, as folhas de estilo do UA concordam com a maioria das coisas. Por exemplo, todos eles tornam os links azul, o texto em geral preto e a cor do plano de fundo branco, mas também há diferenças importantes (e às vezes irritantes) por exemplo, como eles estilizam controles de formulários.

Analise mais detalhadamente a folha de estilo UA do WebKit e o que ela faz em relação ao modo escuro. Faça uma pesquisa completa do texto "escuro" na folha de estilo. O padrão fornecido pela folha de estilo muda dependendo se o modo escuro está ativado ou desativado. Para ilustrar isso, veja uma regra CSS que usa a pseudoclasse :matches e variáveis internas do WebKit, como -apple-system-control-background, bem como a diretiva do pré-processador WebKit-internal #if defined:

input,
input:matches([type="password"], [type="search"]) {
  -webkit-appearance: textfield;
  #if defined(HAVE_OS_DARK_MODE_SUPPORT) &&
      HAVE_OS_DARK_MODE_SUPPORT
    color: text;
    background-color: -apple-system-control-background;
  #else
    background-color: white;
  #endif
  /* snip */
}

Você vai 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 tem cores padronizadas para o sistema semântico. Elas são especificadas no Módulo de cor CSS Nível 4. Por exemplo, Canvas (que não deve ser confundido com a tag <canvas>) é para o plano de fundo do conteúdo ou dos documentos do aplicativo, enquanto CanvasText é para texto no conteúdo ou em documentos de aplicativos. Os dois são usados juntos e não devem ser usados de forma isolada.

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

/**
  Not actual UA stylesheet code.
  For illustrative purposes only.
*/
body {
  color: CanvasText;
  background-color: Canvas
}

A propriedade do CSS color-scheme

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

A propriedade color-scheme definida nela permite que um elemento indique com quais esquemas de cores ele pode ser renderizado. Esses valores são negociados com as preferências do usuário, resultando em um esquema de cores escolhido que afeta elementos da interface do usuário (interface), como as cores padrão dos controles de formulário e das barras de rolagem, bem como os valores usados das cores do sistema CSS. No momento, os seguintes valores são permitidos:

  • normal: indica que o elemento não reconhece esquemas de cores e, por isso, precisa ser renderizado com o esquema de cores padrão do navegador.

  • [ light | dark ]+: indica que o elemento reconhece e pode processar os esquemas de cores listados e expressa uma preferência ordenada entre eles.

Nesta lista, light representa um esquema de cores claras, com cores de plano de fundo claras e cores de primeiro plano escuras, enquanto 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 precisa fazer com que as cores usadas em todas as interfaces fornecidas pelo navegador correspondam à intent do esquema. Exemplos são barras de rolagem, sublinhados de verificação ortográfica, controles de formulários etc.

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

/*
  The page supports both dark and light color schemes,
  and the page author prefers dark.
*/
:root {
  color-scheme: dark light;
}

A metatag color-scheme

Para respeitar a propriedade CSS color-scheme, é necessário fazer o download do CSS primeiro (se for referenciado por <link rel="stylesheet">) e ser analisado. Para ajudar os user agents a renderizar o plano de fundo da página com o esquema de cores desejado imediatamente, um valor color-scheme também pode ser fornecido em um elemento <meta name="color-scheme">.

<!--
  The page supports both dark and light color schemes,
  and the page author prefers dark.
-->
<meta name="color-scheme" content="dark light">

Combinar color-scheme e prefers-color-scheme

Como a metatag e a propriedade CSS (se aplicadas ao elemento :root) resultam no mesmo comportamento, é recomendável especificar o esquema de cores usando a metatag para que o navegador possa adotar o esquema preferencial mais rapidamente.

Embora não sejam necessárias outras regras de CSS para páginas de valor de referência absolutos, no caso geral, é preciso sempre combinar color-scheme com prefers-color-scheme. Por exemplo, a cor CSS proprietária do WebKit -webkit-link, usada pelo WebKit e pelo Chrome para o link azul rgb(0,0,238) clássico, tem uma taxa de contraste insuficiente de 2,23:1 em um fundo preto e não é nos requisitos das WCAG AA e das WCAG.

Abri bugs para o Chrome, WebKit e Firefox, bem como um metaproblema no HTML padrão para corrigir isso.

Interação com prefers-color-scheme

A interação da propriedade CSS color-scheme e da metatag correspondente com o recurso de mídia de preferência do usuário prefers-color-scheme pode parecer confusa no início. Na verdade, eles funcionam muito bem juntos. O mais importante a entender é que color-scheme determina exclusivamente a aparência padrão, enquanto prefers-color-scheme determina a aparência estilizável. Para deixar isso mais claro, considere a seguinte página:

<head>
  <meta name="color-scheme" content="dark light">
  <style>
    fieldset {
      background-color: gainsboro;
    }
    @media (prefers-color-scheme: dark) {
      fieldset {
        background-color: darkslategray;
      }
    }
  </style>
</head>
<body>
  <p>
    Lorem ipsum dolor sit amet, legere ancillae ne vis.
  </p>
  <form>
    <fieldset>
      <legend>Lorem ipsum</legend>
      <button type="button">Lorem ipsum</button>
    </fieldset>
  </form>
</body>

O código CSS inline na página define o background-color do elemento <fieldset> como gainsboro no caso geral e como darkslategray se o usuário preferir um esquema de cores dark de acordo com o recurso de mídia de preferência do usuário prefers-color-scheme.

Por meio do elemento <meta name="color-scheme" content="dark light">, a página informa ao navegador que é compatível com um tema escuro e um claro, com preferência pelo tema escuro.

Dependendo se o sistema operacional está no modo escuro ou claro, a página inteira aparece como claro no escuro ou vice-versa, de acordo com a folha de estilo do user agent. Não há outro CSS fornecido pelo desenvolvedor envolvido para alterar o texto do parágrafo ou a cor de fundo da página.

Observe como a background-color do elemento <fieldset> muda se o modo escuro estiver ativado, de acordo com as regras na folha de estilo inline fornecida pelo desenvolvedor na página. É gainsboro ou darkslategray.

Uma página no modo claro.
Modo claro:estilos especificados pelo desenvolvedor e pelo user agent. O texto é preto e o plano de fundo é branco, de acordo com a folha de estilo do user agent. O background-color do elemento <fieldset> é gainsboro, de acordo com a folha de estilo do desenvolvedor inline.
Uma página no modo escuro.
Modo escuro:estilos especificados pelo desenvolvedor e pelo user agent. O texto é branco e o plano de fundo é preto, de acordo com a folha de estilo do user agent. O background-color do elemento <fieldset> é darkslategray, de acordo com a folha de estilo do desenvolvedor inline.

A aparência do elemento <button> é controlada pela folha de estilo do user agent. A color é definida como a cor do sistema ButtonText, e a background-color e os quatro border-colors são definidos como a cor do sistema ButtonFace.

Uma página do modo claro que usa a propriedade ButtonFace.
Modo claro:o background-color e os vários border-colors são definidos como a cor do sistema ButtonFace.

Agora observe como o border-color do elemento <button> muda. O valor computed para o border-top-color e o border-bottom-color muda de rgba(0, 0, 0, 0.847) (preto) para rgba(255, 255, 255, 0.847) (brilhante), já que o user agent atualiza ButtonFace dinamicamente com base no esquema de cores. O mesmo se aplica ao color do elemento <button> definido como a cor correspondente do sistema ButtonText.

Mostrando que os valores de cor calculados correspondem a ButtonFace.
Modo light:os valores calculados de border-top-color e border-bottom-color que estão definidos como ButtonFace na folha de estilo do user agent agora são rgba(0, 0, 0, 0.847).
Mostrando que os valores de cor calculados ainda correspondem a ButtonFace no modo escuro.
Modo escuro:os valores computados de border-top-color e border-bottom-color definidos como ButtonFace na folha de estilo do user agent agora são rgba(255, 255, 255, 0.847).

Demonstração

É possível conferir os efeitos de color-scheme aplicados a um grande número de elementos HTML em uma demonstração do Glitch. A demonstração mostra deliberadamente a violação das WCAG AA e WCAG AAA com as cores dos links mencionadas no aviso acima.

A demonstração no modo claro.
A demonstração mudou para color-scheme: light.
A demonstração no modo escuro.
A demonstração mudou para color-scheme: dark. Observe a violação WCAG AA e WCAG AAA com as cores dos links.

Agradecimentos

A propriedade CSS color-scheme e a metatag correspondente foram implementadas por Rune Lillesveen. Rune também é coeditora da especificação CSS Color Ajuste Module Level 1. Imagem principal de Philippe Leone no Unsplash (links em inglês).