Un site choisit entre clair et sombre de deux manières : la préférence système du visiteur ou un choix explicite que le site stocke pour ce visiteur. Les composants EmDash lisent les deux signaux à travers une convention sur l’élément <html>. Cette page décrit cette convention, comment donner à un champ d’image une variante sombre et comment la rendre avec le composant Image de emdash/ui.
Convention de thème
Les composants et templates utilisent ces deux signaux, dans cet ordre :
- Une classe
darkoulightsur<html>fixe le schéma. La classe l’emporte sur la préférence système. - Sans classe, le schéma suit la media query
prefers-color-scheme.
Les templates fournis stockent un choix explicite dans un cookie theme et l’appliquent avant le premier affichage avec un script inline dans <head>. Le script suivant lit le cookie et définit la classe, et ne fait rien quand aucun choix n’est stocké :
<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>
Définissez les couleurs une fois avec light-dark() et laissez la classe fixer le schéma :
: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;
}
Un site sans sélecteur de thème n’a pas besoin de script : laissez <html> sans classe et la préférence système s’applique.
Variantes d’image sombre
Un champ d’image peut contenir une seconde image pour les schémas de couleurs sombres. Les rédacteurs la choisissent à côté de l’image principale, et le composant Image affiche celle qui correspond au schéma du visiteur.
Activer le slot sur un champ
Le slot est désactivé par défaut. Activez-le par champ, soit dans l’admin soit dans un fichier seed.
Dans l’admin, ouvrez Content Types, éditez le champ d’image et activez Dark mode variant.
Dans un fichier seed, définissez l’option de widget darkVariant sur le champ :
{
"slug": "featured_image",
"label": "Featured Image",
"type": "image",
"options": { "darkVariant": true }
}
Choisir la variante dans l’éditeur
-
Ouvrez une entrée et sélectionnez l’image principale comme d’habitude.
-
Cliquez sur Add dark mode variant sous l’image et choisissez la variante sombre dans la médiathèque.
-
Enregistrez l’entrée.
La variante est stockée dans la valeur du champ en tant que darkVariant. Supprimer l’image principale supprime la variante avec elle ; remplacer l’image principale conserve la variante jusqu’à ce que vous la remplaciez ou la supprimiez.
Rendre la variante
Le composant Image rend les deux images quand la valeur contient un darkVariant et affiche la correspondante avec CSS. Rien ne change dans le 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 />}
La sortie contient deux éléments <img>. L’image principale reçoit la classe emdash-image--light et la variante reçoit emdash-image--dark. Les deux utilisent le texte alt, les remplacements de largeur et hauteur, et les attributs de chargement de l’image principale. Chacune conserve sa propre couleur de substitution.
Un id que vous passez reste sur l’image principale ; la variante reçoit le même id avec un suffixe --dark, donc id="hero" donne hero et hero--dark.
Quand l’image sombre vient d’ailleurs, comme un second champ d’image, passez-la explicitement :
<Image image={post.data.hero} darkVariant={post.data.hero_dark} />
Comportement de chargement
Les deux images sont lazy par défaut. Les navigateurs ne récupèrent pas une image lazy cachée avec display: none, donc un visiteur ne télécharge que la variante pour son schéma, et l’autre se charge quand le schéma change.
Avec priority, les deux images reçoivent loading="eager" et fetchpriority="high", et les deux se téléchargent dans chaque schéma. Le thème est décidé dans le navigateur, donc le serveur ne peut pas savoir quelle variante un visiteur verra. Utilisez priority sur l’image au-dessus de la ligne de flottaison et laissez les autres images en lazy.
Utiliser une convention de thème différente
Le CSS fourni cache la variante qui ne correspond pas au schéma. Ses sélecteurs utilisent :where() sur la partie <html>, donc toute règle de votre part ciblant <html> avec une classe ou un attribut l’emporte.
Si votre sélecteur définit un attribut comme data-theme, la solution la plus courte est de définir aussi les classes dark et light depuis le même chemin de code. Sinon, remplacez les quatre cas dans votre propre feuille de style :
: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;
}
Faites correspondre la valeur display avec ce que votre feuille de style donne aux images ailleurs, par exemple inline quand vous ne réinitialisez pas img à block.