사이트는 두 가지 방법 중 하나로 라이트와 다크를 결정합니다: 방문자의 시스템 기본 설정, 또는 사이트가 해당 방문자를 위해 저장하는 명시적인 선택입니다. EmDash 컴포넌트는 <html> 요소의 하나의 규칙을 통해 두 신호를 모두 읽습니다. 이 페이지에서는 해당 규칙, 이미지 필드에 다크 변형을 부여하는 방법, emdash/ui의 Image 컴포넌트로 렌더링하는 방법을 설명합니다.
테마 규칙
컴포넌트와 템플릿은 이 두 신호를 다음 순서로 사용합니다:
<html>의dark또는light클래스가 스키마를 고정합니다. 클래스가 시스템 기본 설정보다 우선합니다.- 클래스가 없으면 스키마는
prefers-color-scheme미디어 쿼리를 따릅니다.
번들된 템플릿은 명시적인 선택을 theme 쿠키에 저장하고 <head>의 인라인 스크립트로 첫 번째 페인트 전에 적용합니다. 다음 스크립트는 쿠키를 읽고 클래스를 설정하며, 선택이 저장되지 않았을 때는 아무것도 하지 않습니다:
<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} />
로딩 동작
두 이미지 모두 기본적으로 lazy입니다. 브라우저는 display: none으로 숨겨진 lazy 이미지를 가져오지 않으므로, 방문자는 자신의 스키마에 맞는 변형만 다운로드하고 다른 것은 스키마가 변경될 때 로드됩니다.
priority를 사용하면 두 이미지 모두 loading="eager"와 fetchpriority="high"를 받고, 모든 스키마에서 둘 다 다운로드됩니다. 테마는 브라우저에서 결정되므로 서버는 방문자가 어떤 변형을 볼지 알 수 없습니다. 스크롤 없이 보이는 하나의 이미지에 priority를 사용하고 나머지 이미지는 lazy로 두세요.
다른 테마 규칙 사용하기
제공된 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입니다.