深色模式

本頁內容

網站透過兩種方式在淺色和深色之間做出選擇:訪客的系統偏好,或網站為該訪客儲存的明確選擇。EmDash 元件透過 <html> 元素上的慣例讀取這兩個訊號。本頁描述了該慣例、如何為圖片欄位提供深色變體,以及如何使用 emdash/uiImage 元件渲染它。

主題慣例

元件和範本按以下順序使用這兩個訊號:

  1. <html> 上的 darklight 類別固定配色方案。類別優先於系統偏好。
  2. 沒有類別時,配色方案跟隨 prefers-color-scheme 媒體查詢。

隨附的範本將明確選擇儲存在 theme cookie 中,並在 <head> 中使用行內指令碼在首次渲染前套用。以下指令碼讀取 cookie 並設定類別,當沒有儲存選擇時不執行任何操作:

<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>

使用 light-dark() 定義一次顏色,讓類別固定配色方案:

: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;
}

沒有主題切換器的網站不需要指令碼:讓 <html> 沒有類別,系統偏好就會生效。

深色圖片變體

圖片欄位可以包含用於深色配色方案的第二張圖片。編輯在主圖片旁邊選擇它,Image 元件顯示與訪客配色方案匹配的那張。

在欄位上啟用插槽

插槽預設關閉。在管理後台或種子檔案中按欄位啟用。

在管理後台中,開啟 Content Types,編輯圖片欄位,開啟 Dark mode variant

在種子檔案中,在欄位上設定 darkVariant 元件選項:

{
	"slug": "featured_image",
	"label": "Featured Image",
	"type": "image",
	"options": { "darkVariant": true }
}

在編輯器中選擇變體

  1. 開啟一個條目,像往常一樣選擇主圖片。

  2. 點擊圖片下方的 Add dark mode variant,從媒體庫中選擇深色變體。

  3. 儲存條目。

變體儲存在欄位值中的 darkVariant。刪除主圖片會一併刪除變體;替換主圖片會保留變體直到您替換或刪除它。

渲染變體

當值包含 darkVariant 時,Image 元件渲染兩張圖片,並使用 CSS 顯示匹配的那張。範本中無需任何變更:

---
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 />}

輸出包含兩個 <img> 元素。主圖片獲得類別 emdash-image--light,變體獲得 emdash-image--dark。兩者都使用主圖片的 alt 文字、寬高覆蓋和載入屬性。每個保留自己的佔位符顏色。

您傳遞的 id 保留在主圖片上;變體獲得相同的 id 加上 --dark 後綴,因此 id="hero" 產生 herohero--dark

當深色圖片來自其他地方,例如第二個圖片欄位,請明確傳遞:

<Image image={post.data.hero} darkVariant={post.data.hero_dark} />

載入行為

兩張圖片預設是延遲載入的。瀏覽器不會取得使用 display: none 隱藏的延遲載入圖片,因此訪客只下載其配色方案的變體,另一個在配色方案變更時載入。

使用 priority 時,兩張圖片都獲得 loading="eager"fetchpriority="high",在每種配色方案中都會下載。主題在瀏覽器中決定,因此伺服器無法知道訪客將看到哪個變體。在首屏圖片上使用 priority,其他圖片保持延遲載入。

使用不同的主題慣例

附帶的 CSS 隱藏與配色方案不匹配的變體。其選擇器在 <html> 部分使用 :where(),因此任何使用類別或屬性定位 <html> 的規則都會優先。

如果您的切換器設定了 data-theme 等屬性,最簡單的修復是在同一程式碼路徑中也設定 darklight 類別。否則,在您自己的樣式表中覆蓋四種情況:

: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;
}

display 值與您的樣式表在其他地方給圖片的值匹配,例如當您不將 img 重設為 block 時使用 inline