網站透過兩種方式之一在淺色和深色之間做出選擇:訪客的系統偏好,或網站為該訪客儲存的明確選擇。EmDash 元件透過 <html> 元素上的一個慣例讀取兩個訊號。本頁描述該慣例、如何為圖片欄位提供深色變體,以及如何使用 emdash/ui 中的 Image 元件進行渲染。
主題慣例
元件和範本按以下順序使用這兩個訊號:
<html>上的dark或light類別固定方案。類別優先於系統偏好。- 沒有類別時,方案遵循
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 }
}
在編輯器中選擇變體
-
開啟一個項目並像平常一樣選擇主圖片。
-
點擊圖片下方的 Add dark mode variant,從媒體庫中選擇深色變體。
-
儲存項目。
變體作為 darkVariant 儲存在欄位值內部。移除主圖片會同時移除變體;替換主圖片會保留變體,直到你替換或移除它。
渲染變體
Image 元件在值攜帶 darkVariant 時渲染兩張圖片,並使用 CSS 顯示匹配的那張。範本中無需更改:
---
import { decodeSlug, getEmDashEntry } from "emdash";
import { Image } from "emdash/ui";
const slug = decodeSlug(Astro.params.slug);
if (!slug) {
return Astro.redirect("/404");
}
const { entry: post } = await getEmDashEntry("posts", slug);
if (!post) {
return Astro.redirect("/404");
}
---
{post.data.featured_image && <Image image={post.data.featured_image} priority />}
輸出包含兩個 <img> 元素。主圖片獲得類別 emdash-image--light,變體獲得 emdash-image--dark。兩者都使用主圖片的替代文字、寬高覆寫和載入屬性。每個保留自己的佔位符顏色。
你傳遞的 id 保留在主圖片上;變體獲得帶 --dark 後綴的相同 id,因此 id="hero" 產生 hero 和 hero--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 之類的屬性,最短的修復是同樣從同一程式碼路徑設定 dark 和 light 類別。否則,在你自己的樣式表中覆寫四種情況:
: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。