Un sito decide tra chiaro e scuro in due modi: la preferenza di sistema del visitatore o una scelta esplicita che il sito memorizza per quel visitatore. I componenti EmDash leggono entrambi i segnali attraverso una convenzione sull’elemento <html>. Questa pagina descrive quella convenzione, come dare a un campo immagine una variante scura e come renderizzarla con il componente Image da emdash/ui.
Convenzione del tema
Componenti e template usano questi due segnali, in quest’ordine:
- Una classe
darkolightsu<html>fissa lo schema. La classe prevale sulla preferenza di sistema. - Senza classe, lo schema segue la media query
prefers-color-scheme.
I template forniti memorizzano una scelta esplicita in un cookie theme e la applicano prima del primo rendering con uno script inline in <head>. Lo script seguente legge il cookie e imposta la classe, e non fa nulla quando nessuna scelta è memorizzata:
<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>
Definite i colori una volta con light-dark() e lasciate che la classe fissi lo schema:
: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 sito senza selettore di tema non ha bisogno di script: lasciate <html> senza classe e la preferenza di sistema si applica.
Varianti di immagine scura
Un campo immagine può contenere una seconda immagine per gli schemi di colore scuri. I redattori la selezionano accanto all’immagine principale, e il componente Image mostra quella che corrisponde allo schema del visitatore.
Abilitare lo slot su un campo
Lo slot è disattivato per impostazione predefinita. Attivatelo per campo, sia nell’admin che in un file seed.
Nell’admin, aprite Content Types, modificate il campo immagine e attivate Dark mode variant.
In un file seed, impostate l’opzione widget darkVariant sul campo:
{
"slug": "featured_image",
"label": "Featured Image",
"type": "image",
"options": { "darkVariant": true }
}
Scegliere la variante nell’editor
-
Aprite una voce e selezionate l’immagine principale come al solito.
-
Cliccate su Add dark mode variant sotto l’immagine e scegliete la variante scura dalla libreria multimediale.
-
Salvate la voce.
La variante è memorizzata nel valore del campo come darkVariant. Rimuovere l’immagine principale rimuove anche la variante; sostituire l’immagine principale mantiene la variante fino a quando non la sostituite o rimuovete.
Renderizzare la variante
Il componente Image renderizza entrambe le immagini quando il valore contiene un darkVariant e mostra quella corrispondente con CSS. Nulla cambia nel 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 />}
L’output contiene due elementi <img>. L’immagine principale ottiene la classe emdash-image--light e la variante ottiene emdash-image--dark. Entrambe usano il testo alt, le sovrascritture di larghezza e altezza e gli attributi di caricamento dell’immagine principale. Ciascuna mantiene il proprio colore segnaposto.
Un id che passate resta sull’immagine principale; la variante ottiene lo stesso id con un suffisso --dark, quindi id="hero" produce hero e hero--dark.
Quando l’immagine scura proviene da altrove, come un secondo campo immagine, passatela esplicitamente:
<Image image={post.data.hero} darkVariant={post.data.hero_dark} />
Comportamento di caricamento
Entrambe le immagini sono lazy per impostazione predefinita. I browser non scaricano un’immagine lazy nascosta con display: none, quindi un visitatore scarica solo la variante per il suo schema, e l’altra si carica quando lo schema cambia.
Con priority, entrambe le immagini ottengono loading="eager" e fetchpriority="high", e entrambe vengono scaricate in ogni schema. Il tema viene deciso nel browser, quindi il server non può sapere quale variante vedrà un visitatore. Usate priority sull’unica immagine sopra la piega e lasciate le altre immagini lazy.
Usare una convenzione di tema diversa
Il CSS fornito nasconde la variante che non corrisponde allo schema. I suoi selettori usano :where() sulla parte <html>, quindi qualsiasi vostra regola che punta a <html> con una classe o attributo prevale.
Se il vostro selettore imposta un attributo come data-theme, la soluzione più breve è impostare anche le classi dark e light dallo stesso percorso di codice. Altrimenti, sovrascrivete i quattro casi nel vostro foglio di stile:
: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;
}
Fate corrispondere il valore display a quello che il vostro foglio di stile dà alle immagini altrove, per esempio inline quando non resettate img a block.