Um site decide entre claro e escuro de duas maneiras: a preferência do sistema do visitante ou uma escolha explícita que o site armazena para aquele visitante. Os componentes EmDash leem ambos os sinais através de uma convenção no elemento <html>. Esta página descreve essa convenção, como dar a um campo de imagem uma variante escura e como renderizá-la com o componente Image de emdash/ui.
Convenção de tema
Componentes e templates usam estes dois sinais, nesta ordem:
- Uma classe
darkoulightno<html>fixa o esquema. A classe prevalece sobre a preferência do sistema. - Sem classe, o esquema segue a media query
prefers-color-scheme.
Os templates incluídos armazenam uma escolha explícita em um cookie theme e a aplicam antes da primeira renderização com um script inline no <head>. O script a seguir lê o cookie e define a classe, e não faz nada quando nenhuma escolha está armazenada:
<script is:inline>
(function () {
var c = document.cookie;
var i = c.indexOf("theme=");
var theme = i >= 0 ? c.slice(i + 6).split(";")[0] : null;
if (theme === "dark" || theme === "light") {
document.documentElement.classList.add(theme);
}
})();
</script>
Defina cores uma vez com light-dark() e deixe a classe fixar o esquema:
:root {
color-scheme: light dark;
--color-bg: light-dark(#ffffff, #0d0d0d);
--color-text: light-dark(#1a1a1a, #ededed);
}
:root.light {
color-scheme: light;
}
:root.dark {
color-scheme: dark;
}
Um site sem seletor de tema não precisa de script: deixe <html> sem classe e a preferência do sistema se aplica.
Variantes de imagem escura
Um campo de imagem pode conter uma segunda imagem para esquemas de cores escuros. Os editores a selecionam ao lado da imagem principal, e o componente Image mostra a que corresponde ao esquema do visitante.
Ativar o slot em um campo
O slot está desativado por padrão. Ative-o por campo, seja no admin ou em um arquivo seed.
No admin, abra Content Types, edite o campo de imagem e ative Dark mode variant.
Em um arquivo seed, defina a opção de widget darkVariant no campo:
{
"slug": "featured_image",
"label": "Featured Image",
"type": "image",
"options": { "darkVariant": true }
}
Escolher a variante no editor
-
Abra uma entrada e selecione a imagem principal como de costume.
-
Clique em Add dark mode variant abaixo da imagem e escolha a variante escura da biblioteca de mídia.
-
Salve a entrada.
A variante é armazenada dentro do valor do campo como darkVariant. Remover a imagem principal remove a variante com ela; substituir a imagem principal mantém a variante até você substituí-la ou removê-la.
Renderizar a variante
O componente Image renderiza ambas as imagens quando o valor contém um darkVariant e mostra a correspondente com CSS. Nada muda no template:
---
import { Image } from "emdash/ui";
import { getEmDashEntry } from "emdash";
const { entry: post } = await getEmDashEntry("posts", Astro.params.slug);
---
{post?.data.featured_image && <Image image={post.data.featured_image} priority />}
A saída contém dois elementos <img>. A imagem principal recebe a classe emdash-image--light e a variante recebe emdash-image--dark. Ambas usam o texto alt, as sobreposições de largura e altura, e os atributos de carregamento da imagem principal. Cada uma mantém sua própria cor de placeholder.
Um id que você passa fica na imagem principal; a variante recebe o mesmo id com um sufixo --dark, então id="hero" produz hero e hero--dark.
Quando a imagem escura vem de outro lugar, como um segundo campo de imagem, passe-a explicitamente:
<Image image={post.data.hero} darkVariant={post.data.hero_dark} />
Comportamento de carregamento
Ambas as imagens são lazy por padrão. Navegadores não buscam uma imagem lazy que está oculta com display: none, então um visitante baixa apenas a variante para seu esquema, e a outra carrega quando o esquema muda.
Com priority, ambas as imagens recebem loading="eager" e fetchpriority="high", e ambas são baixadas em todos os esquemas. O tema é decidido no navegador, então o servidor não pode saber qual variante um visitante verá. Use priority na imagem acima da dobra e deixe outras imagens lazy.
Usar uma convenção de tema diferente
O CSS incluído oculta a variante que não corresponde ao esquema. Seus seletores usam :where() na parte <html>, então qualquer regra sua que tenha como alvo <html> com uma classe ou atributo prevalece.
Se seu seletor define um atributo como data-theme, a correção mais curta é também definir as classes dark e light do mesmo caminho de código. Caso contrário, sobrescreva os quatro casos em sua própria folha de estilos:
:root[data-theme="dark"] .emdash-image--light,
:root[data-theme="light"] .emdash-image--dark {
display: none;
}
:root[data-theme="dark"] .emdash-image--dark,
:root[data-theme="light"] .emdash-image--light {
display: block;
}
Combine o valor display com o que sua folha de estilos dá às imagens em outros lugares, por exemplo inline quando você não reseta img para block.