Embora seja mais comum definir a propriedade color-scheme na raiz, ela pode ser definida em elementos individuais para forçar um esquema de cores diferente do restante da página.
Isso pode ser útil para componentes que precisam ser sempre visualizados em um esquema de cores específico (por exemplo, sempre no modo escuro ou claro).
Como exemplos de casos de uso, temos:
- Elementos que costumam estar no modo escuro, mesmo em páginas no modo claro, por motivos estéticos, como blocos de código, players de mídia e galerias de fotos
- As áreas que contêm mídia projetada para um fundo claro (por exemplo, imagens, vídeos, ilustrações, visualizações de impressão) podem ser definidas para o modo claro, mesmo que o restante da página esteja no modo escuro.
- Elementos cujo esquema de cores é controlado por uma configuração no nível do usuário, como prévias de componentes
- Incorporações que não são compatíveis com os modos claro e escuro
- Ferramentas de design, mapas, visualizações, jogos etc.
Quando mudar as cores e quando forçar o color-scheme?
Nem todo elemento que usa texto mais claro em um plano de fundo mais escuro no modo claro ou texto mais escuro em um plano de fundo mais claro no modo escuro precisa de um color-scheme diferente.
Por exemplo, um botão principal pode ser renderizado em azul com texto branco no modo claro, mas isso não garante um color-scheme: dark.
Como regra geral, os elementos que usam um color-scheme diferente costumam ser superfícies complexas que estabelecem o próprio contexto visual, em vez de contêineres simples e rasos.
Ao considerar o uso de um color-scheme diferente em um elemento, pergunte-se:
- A interface integrada do navegador que não é personalizada (por exemplo, controles de formulário, barras de rolagem etc.) deve usar esse esquema de cores ou se adaptar ao esquema de cores da página? -> Se for o primeiro caso, não use
color-scheme. - As cores de
light-dark()devem ser resolvidas como no restante da página ou com base na substituição? -> Se for o primeiro caso, não usecolor-scheme. - Os descendentes devem estar nesse
color-scheme? Caso contrário, não usecolor-scheme.
Implementação básica
As substituições específicas de componentes geralmente são usadas (embora não necessariamente) em páginas que também oferecem suporte a vários esquemas de cores por meio de um color-scheme global.
Para implementar o modo escuro em toda a página, consulte Modo escuro.
Depois que um color-scheme em toda a página estiver em vigor e você estiver usando tokens de cor sensíveis a ele (por exemplo, via light-dark()), basta definir color-scheme em componentes específicos para substituir o modo de cor dessa subárvore:
pre, code, .dark {
color-scheme: dark;
}
Alguns navegadores adaptam automaticamente os componentes a um esquema de cores diferente.
Para forçar o esquema de cores especificado em todos os casos, use only, ou seja, color-scheme: only dark; em vez de color-scheme: dark;.
Como adaptar valores que não são de cor
No momento, light-dark() só funciona para cores.
Práticas recomendadas
- OBRIGATÓRIO: não defina
color-schemeem elementos sem um plano de fundo, porque isso pode misturar pares de cores de plano de fundo e de texto de diferentes esquemas de cores, resultando em texto ilegível. - OPCIONAL: embora seja mais fácil reutilizar os mesmos pares de cores do modo escuro de toda a página, podemos definir pares de cores diferentes para esses componentes. Por exemplo, talvez você queira que um componente do modo escuro usado em uma página do modo claro seja um pouco menos escuro do que quando o mesmo componente é usado em uma página que está totalmente no modo escuro.
Problemas conhecidos que você precisa saber
Pegadinha importante: herança de cores light-dark()
light-dark() é resolvido no momento do valor computado.
Isso significa que todas as propriedades <color> herdadas definidas como uma cor light-dark() vão transmitir apenas uma das duas cores para os descendentes, não a expressão light-dark() em si.
Isso inclui:
- Propriedades de cor integradas que herdam, como
color,accent-color,fill,stroke,text-shadow,caret-color - Todas as propriedades personalizadas herdáveis registradas com
syntax: <color>einherits: true - Qualquer outra propriedade
<color>definida comoinherit
Isso significa que você deve:
- NÃO registre propriedades personalizadas destinadas a armazenar tokens de design (por exemplo,
--surface-color) como<color>. Os tokens precisam manter a expressãolight-dark()ativa para que os descendentes possam resolvê-los novamente em umcolor-schemediferente. - Ao definir
color-schemeem um elemento, especifique novamente as propriedades<color>herdadas que podem ter sido definidas como valoreslight-dark()(diretamente ou por tokens de design), mesmo que seja para o mesmo token de design. - NÃO use
inheritem propriedades<color>em elementos com uma substituiçãocolor-scheme(pode ser usado nos descendentes). - RECOMENDAMOS usar propriedades
<color>registradas para o caso de uso oposto: quando você quer capturar deliberadamente a cor resolvida do ancestral e impedir que ela seja resolvida novamente nocolor-schemedo descendente. Por exemplo, capturar o plano de fundo da página para usar em outro lugar. - Se você precisar animar uma cor, use uma propriedade
<color>separada registrada em@propertyno elemento que está sendo animado (o registro é necessário para a interpolação de cores). Esse não é um token de design, mas um destino de animação por elemento, então não entra em conflito com a regra acima.
Exemplo:
:root {
--accent-color: light-dark(blue, skyblue);
--surface-color: light-dark(white, #222);
--text-color: light-dark(#111, white);
color-scheme: light dark;
accent-color: var(--accent-color);
color: var(--text-color);
}
body {
/* --surface-color dynamically switches despite being inherited because --surface-color is not registered */
background: var(--surface-color);
}
pre, code {
color-scheme: dark;
background: var(--surface-color);
/* Without this, accent-color would be blue, not skyblue! */
accent-color: var(--accent-color);
/* Without this, text-color would be #111, not white! */
color: var(--text-color);
}
Problemas que podem ocorrer ao usar color-scheme
- O Chrome e o Firefox respeitam
color-schemepara iframes: eles renderizam páginas incorporadas no esquema de cores correto e ajustam a consulta de mídiaprefers-color-schemeda página incorporada para refletir ocolor-schemedo contexto de incorporação. O Safari não faz isso e resolveprefers-color-schemepara a configuração do sistema, mesmo dentro de iframes.- Se você controla o elemento pai e o iframe: transmita o esquema de cores do elemento pai para o iframe de forma explícita, usando um parâmetro de URL (
?theme=dark) no momento da criação do iframe ou usandopostMessage()(que também permite reagir a mudanças no ambiente de execução). No iframe, defina uma classe em<html>(e/oucolor-schemeem:root) com base nesse indicador, em vez de usarprefers-color-scheme. - Se você controla apenas a página incorporada: não há uma maneira confiável de detectar o
color-schemedo contexto de incorporação de dentro do iframe no Safari. Exponha um parâmetro de tema explícito na API de incorporação (por exemplo, uma string de consulta ou um protocolopostMessage) e documente-o para os incorporadores.
- Se você controla o elemento pai e o iframe: transmita o esquema de cores do elemento pai para o iframe de forma explícita, usando um parâmetro de URL (
Estratégias de fallback
Alternativas e suporte do navegador para color-scheme
A propriedade color-scheme é um aprimoramento progressivo.
Os navegadores que não oferecem suporte a essa propriedade vão ignorá-la e usar a interface padrão do modo claro.
Para se adaptar às preferências do usuário em navegadores mais antigos, use consultas de mídia prefers-color-scheme para fornecer cores diferentes quando o modo escuro for preferido.
- USE a consulta de mídia para alternar as propriedades personalizadas em
:rootouhtml. - Evite usar a consulta de mídia em componentes individuais, a menos que o componente exija um tipo muito específico de personalização do modo escuro além das cores.
:root {
/* Define brand colors for each mode */
--color-brand-light: #0056b3;
--color-brand-dark: #00e5ff;
--color-brand: var(--color-brand-light);
/* MANDATORY: Fallback for browsers without light-dark support */
@media (prefers-color-scheme: dark) {
--color-brand: var(--color-brand-dark);
}
/* Ignored in older browsers */
color-scheme: light dark;
}
button.primary {
background-color: var(--color-brand);
}
Alternativas e suporte do navegador para light-dark()
Para navegadores que oferecem suporte a color-scheme, mas ainda não a light-dark(), as versões claras e escuras das cores precisam ser definidas primeiro como propriedades personalizadas, e a consulta de mídia prefers-color-scheme precisa ser usada para definir cores para o respectivo modo, como no exemplo abaixo:
:root {
/* Define browser UI accent color for each mode */
--brand-accent-light: #0056b3;
--brand-accent-dark: #00e5ff;
--accent-color: var(--brand-accent-light);
/* MANDATORY: Fallback for browsers without light-dark support */
@media (prefers-color-scheme: dark) {
--accent-color: var(--brand-accent-dark);
}
/* OPTIONAL: use light-dark() for more control of built-in UI colors */
@supports (color: light-dark(white, black)) {
--accent-color: light-dark(var(--brand-accent-light), var(--brand-accent-dark));
}
/* MANDATORY: Automatically adapt native UI to user system preferences */
color-scheme: light dark;
/* Example inherited color property */
accent-color: var(--accent-color);
}
pre, code {
color-scheme: dark;
/* **Mandatory**: any inherited color properties must be set again, even if to the same design tokens */
accent-color: var(--accent-color);
}