사이트는 두 가지 방법 중 하나로 라이트와 다크를 결정합니다. 방문자의 시스템 환경설정, 또는 사이트가 해당 방문자를 위해 저장한 명시적인 선택입니다. 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로 저장됩니다. 기본 이미지를 제거하면 변형도 함께 제거됩니다. 기본 이미지를 교체하면 변형을 교체하거나 제거할 때까지 변형이 유지됩니다.
변형 렌더링하기
값에 darkVariant가 있으면 Image 컴포넌트는 두 이미지를 모두 렌더링하고 CSS로 일치하는 이미지를 표시합니다. 템플릿은 바꿀 필요가 없습니다.
---
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 />}
출력에는 두 개의 <img> 요소가 포함됩니다. 기본 이미지에는 클래스 emdash-image--light가, 변형에는 emdash-image--dark가 붙습니다. 둘 다 기본 이미지의 alt 텍스트, 너비와 높이 재정의, 로딩 속성을 사용합니다. 각 이미지는 자신만의 플레이스홀더 색상을 유지합니다.
전달한 id는 기본 이미지에 그대로 유지됩니다. 변형은 같은 id에 --dark 접미사가 붙으므로, 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을 사용합니다.