Eine Site entscheidet auf eine von zwei Arten zwischen hell und dunkel: anhand der Systemeinstellung des Besuchers oder anhand einer ausdrücklichen Wahl, die die Site für diesen Besucher speichert. EmDash-Komponenten lesen beide Signale über eine einzige Konvention auf dem <html>-Element. Diese Seite beschreibt diese Konvention, wie Sie einem Bildfeld eine dunkle Variante geben und wie Sie sie mit der Image-Komponente aus emdash/ui rendern.
Theme-Konvention
Komponenten und Templates verwenden diese beiden Signale in dieser Reihenfolge:
- Eine Klasse
darkoderlightauf<html>legt das Farbschema fest. Die Klasse hat Vorrang vor der Systemeinstellung. - Ohne Klasse folgt das Farbschema der Media Query
prefers-color-scheme.
Die mitgelieferten Templates speichern eine ausdrückliche Wahl in einem theme-Cookie und wenden sie vor dem ersten Rendern mit einem Inline-Skript im <head> an. Das folgende Skript liest das Cookie und setzt die Klasse; ist keine Wahl gespeichert, tut es nichts:
<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>
Definieren Sie Farben einmal mit light-dark() und lassen Sie die Klasse das Farbschema festlegen:
: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;
}
Eine Site ohne Theme-Umschalter braucht kein Skript: Lassen Sie <html> ohne Klasse, dann gilt die Systemeinstellung.
Dunkle Bildvarianten
Ein Bildfeld kann ein zweites Bild für dunkle Farbschemata enthalten. Redakteure wählen es neben dem Hauptbild aus, und die Image-Komponente zeigt dasjenige an, das zum Schema des Besuchers passt.
Den Slot an einem Feld aktivieren
Der Slot ist standardmäßig deaktiviert. Aktivieren Sie ihn pro Feld, entweder im Admin oder in einer Seed-Datei.
Öffnen Sie im Admin Content Types, bearbeiten Sie das Bildfeld und schalten Sie Dark mode variant ein.
Setzen Sie in einer Seed-Datei die Widget-Option darkVariant am Feld:
{
"slug": "featured_image",
"label": "Featured Image",
"type": "image",
"options": { "darkVariant": true }
}
Die Variante im Editor auswählen
-
Öffnen Sie einen Eintrag und wählen Sie das Hauptbild wie gewohnt aus.
-
Klicken Sie unter dem Bild auf Add dark mode variant und wählen Sie das dunkle Pendant aus der Medienbibliothek.
-
Speichern Sie den Eintrag.
Die Variante wird als darkVariant im Feldwert gespeichert. Wird das Hauptbild entfernt, wird auch die Variante entfernt; wird das Hauptbild ersetzt, bleibt die Variante erhalten, bis Sie sie ersetzen oder entfernen.
Die Variante rendern
Die Image-Komponente rendert beide Bilder, wenn der Wert eine darkVariant enthält, und zeigt das passende per CSS an. Am Template ändert sich nichts:
---
import { decodeSlug, getEmDashEntry } from "emdash";
import { Image } from "emdash/ui";
const slug = decodeSlug(Astro.params.slug);
if (!slug) {
return Astro.rewrite("/404");
}
const { entry: post } = await getEmDashEntry("posts", slug);
if (!post) {
return Astro.rewrite("/404");
}
---
{post.data.featured_image && <Image image={post.data.featured_image} priority />}
Die Ausgabe enthält zwei <img>-Elemente. Das Hauptbild erhält die Klasse emdash-image--light, die Variante emdash-image--dark. Beide verwenden den alt-Text, die Überschreibungen für Breite und Höhe sowie die Ladeattribute des Hauptbilds. Jedes behält seine eigene Platzhalterfarbe.
Eine von Ihnen übergebene id bleibt am Hauptbild; die Variante erhält dieselbe id mit dem Suffix --dark, sodass id="hero" zu hero und hero--dark führt.
Stammt das dunkle Bild von anderswo, etwa aus einem zweiten Bildfeld, übergeben Sie es explizit:
<Image image={post.data.hero} darkVariant={post.data.hero_dark} />
Ladeverhalten
Beide Bilder werden standardmäßig lazy geladen. Browser laden ein mit display: none ausgeblendetes Lazy-Bild nicht, sodass ein Besucher nur die Variante für sein Schema herunterlädt; die andere wird geladen, wenn sich das Schema ändert.
Mit priority erhalten beide Bilder loading="eager" und fetchpriority="high" und werden in jedem Schema heruntergeladen. Das Theme wird im Browser festgelegt, daher kann der Server nicht wissen, welche Variante ein Besucher sehen wird. Verwenden Sie priority für das eine Bild im sichtbaren Bereich und lassen Sie andere Bilder lazy.
Eine andere Theme-Konvention verwenden
Das mitgelieferte CSS blendet die Variante aus, die nicht zum Schema passt. Seine Selektoren verwenden :where() für den <html>-Teil, sodass jede eigene Regel, die <html> mit einer Klasse oder einem Attribut anspricht, Vorrang hat.
Setzt Ihr Umschalter ein Attribut wie data-theme, ist die kürzeste Lösung, im selben Codepfad zusätzlich die Klassen dark und light zu setzen. Andernfalls überschreiben Sie die vier Fälle in Ihrem eigenen Stylesheet:
: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;
}
Passen Sie den display-Wert an das an, was Ihr Stylesheet Bildern an anderer Stelle gibt, zum Beispiel inline, wenn Sie img nicht auf block zurücksetzen.