Using Tailwind CSS to style your site in dark mode.
다크모드는 많은 OS에서 지원하는 기본 기능이기 때문에, default design과 함께 웹사이트의 dark version을 디자인하는 것이 점점 더 흔해지고 있다.
Tailwind는 이를 쉽게 적용할 수 있도록, ‘dark’ variant를 제공한다.
<div class="bg-white **dark:bg-slate-800** rounded-lg px-6 py-8 ring-1 ring-slate-900/5 shadow-xl">
<div>
<span class="inline-flex items-center justify-center p-2 bg-indigo-500 rounded-md shadow-lg">
<svg class="h-6 w-6 text-white" xmlns="<http://www.w3.org/2000/svg>" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><!-- ... --></svg>
</span>
</div>
<h3 class="text-slate-900 **dark:text-white** mt-5 text-base font-medium tracking-tight">Writes Upside-Down</h3>
<p class="text-slate-500 **dark:text-slate-400** mt-2 text-sm">
The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space.
</p>
</div>
‘prefers-color-scheme’이라는 CSS media 기능을 사용하지만, 바로 다음에 배울 ‘selector’ strategy를 사용하여 다크 모드 toggling을 지원하는 웹사이트를 만들 수도 있다.
prefers-color-scheme 은 CSS 미디어 쿼리의 일종으로, 사용자의 시스템 환경설정에 따라 light mode와 dark mode 스타일을 적용할 수 있도록 해준다.OS 시스템에 의존하는 대신 수동으로 dark mode를 toggling할 수 있도록 하려면, ‘media’ strategy 대신 ‘selector’ strategy를 사용하면 된다. (’selector’ strategy는 v3.4.1부터 기존 ‘class’ strategy를 대체하게 되었다고 한다. 최신 버전이 v3.4.3이니까 꽤 최근 업데이트네)
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: 'selector',
// ...
}
위처럼 설정하게 되면, 이제 ‘dark:{class}’ 클래스는 이전 HTML 트리에 ‘dark’ class가 존재해야만 적용되게 된다.
<!-- Dark mode not enabled -->
<html>
<body>
<!-- Will be white -->
<div class="bg-white dark:bg-black">
<!-- ... -->
</div>
</body>
</html>
<!-- Dark mode enabled -->
<html **class="dark"**>
<body>
<!-- Will be black -->
<div class="bg-white dark:bg-black">
<!-- ... -->
</div>
</body>
</html>
dark class에도 해당 prefix를 추가해야 한다는 것을 잊으면 안된다. 예를들어 tw- prefix를 설정한 경우, tw-dark 클래스를 사용해야 한다는 것이다.dark 클래스를 어떻게 html element에 추가할 것인지는 나에게 달렸다고 한다. 흔히 사용하는 방법은 JavaScript를 사용해서 preference를 읽어서(localStorage가 될수도 있고. 리액트에서 관리하고 있는 전역 상태를 사용할 수도 있을 것 같고), 그에 맞춰 DOM을 업데이트 하는 방법이 있다.NativeScript와 같은 몇몇 프레임워크들은 dark mode를 적용하는 자신들만의 방법이 있어서, dark mode가 active할때 다른 클래스 이름을 사용하는 경우가 있다고 한다.
이런 경우에는 darkMode를 배열로 설정하여 custom selector를 두번째 아이템에 추가해주면 된다고 한다.
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ['selector', '[data-mode="dark"]'],
// ...
}
window.matchMedia() API를 사용하면 selector strategy를 시스템 preference와 수동 toggling을 둘다 동시에 지원하는데 사용할 수도 있다고 한다.
// On page load or when changing themes,
// best to add inline in `head` to avoid FOUC
if (localStorage.theme === 'dark' ||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
// Whenever the user explicitly chooses light mode
localStorage.theme = 'light'
// Whenever the user explicitly chooses dark mode
localStorage.theme = 'dark'
// Whenever the user explicitly chooses to respect the OS preference
localStorage.removeItem('theme')
localStorage.theme이 ‘dark’이거나, localSotrage에 theme이 없고, 시스템 preference가 dark일때 dark mode를 적용하도록 하고 있는 것을 알 수 있다. 즉 manual toggling과 OS preference를 둘다 고려하여 dark mode를 적용하고 있는 것이다.