Tailwind CSS로 다크 모드/라이트 모드 구현하기

Yejin Yang·2024년 6월 26일
0

[TIL]

목록 보기
68/69
post-thumbnail

프로젝트 환경

  • Next.js Pages 환경입니다.
  • 기존 css 은 대부분 Tailwind CSS로 이루어져있는 프로젝트 입니다.

tailwind.config.js 파일 수정

/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: 'selector',
  // ...
}

테일윈드 공식 문서

  • 수동으로 모드 전환을 지원하려면 'selector'를 사용하면 됩니다.
  • 운영체제에 따라가게 하려면 'media'를 사용하면 될 것 같습니다.

모든 요소마다 'dark'라는 prefix 설정하기

<!-- 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라는 프리픽스를 넣어주며 모드에 맞는 디자인을 해야합니다(노가다 시작)
tailwind.config.js의 colors에 셋팅해준 컬러 테마로 빠르게 작업해줍니다~

_document.tsx 파일 수정

Next.js 프로젝트의 _document.tsx 파일에서 초기 로드 시 로컬 스토리지에서 다크 모드 설정을 가져와 HTML 태그의 클래스를 설정하는 스크립트를 추가했습니다.

import Document, { Html, Head, Main, NextScript } from 'next/document';
import Script from 'next/script';

class MyDocument extends Document {
  render() {
    return (
      <Html lang="ko">
        <Head>
            <Script id="theme-init" strategy="beforeInteractive">
            {`
              (function() {
                const rootElement = document.documentElement;
                const colorMode = window.localStorage.getItem('color_mode') || 'light';
                rootElement.className = colorMode;
              })();
            `}
          </Script>
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

페이지가 로드되기 전에 실행되어 로컬 스토리지에서 저장된 color_mode 값을 가져와 HTML 태그의 클래스를 설정합니다.

해당 스크립트가 없어도 모드 전환은 가능했지만 페이지 이동 시, DOM을 새로 그리는 경우, 예를들어 window.location.href를 사용하여 이동하는 경우 초기화 되어서
스크립트로 init하는 과정이 필요했습니다.

Next.js에서 테마 초기 설정을 위해 beforeInteractive 전략을 사용하는 이유는 페이지가 로드되기 전에 사용자의 다크 모드 설정을 적용하기 위함입니다.

beforeInteractive는 페이지가 상호작용하기 전에 스크립트를 실행합니다.

  • 초기 테마 적용: 페이지가 로드되기 전에 다크 모드 또는 라이트 모드를 적용하여 사용자가 깜빡임 없이 테마를 볼 수 있도록 합니다.
  • 빠른 사용자 경험: 사용자가 페이지를 처음 로드할 때 설정된 테마가 즉시 반영되므로 더 나은 사용자 경험을 제공합니다.

ThemeToggle 컴포넌트 작성

다크 모드와 라이트 모드를 전환할 수 있는 ThemeToggle 컴포넌트를 만들었습니다.

import { useEffect, useState } from 'react';

const Toggle = ({ onClick, toggle }) => (
  <button onClick={onClick}>
    {toggle ? '다크' : '라이트'}
  </button>
);

export default function ThemeToggle() {
  const [colorMode, setColorMode] = useState('light');

  useEffect(() => {
    const storedColorMode = window.localStorage.getItem('color_mode') || 'light';
    setColorMode(storedColorMode);
  }, []);

  const handleChangeMode = () => {
    const htmlElement = document.querySelector('html');
    if (!htmlElement) return;

    const newColorMode = colorMode === 'light' ? 'dark' : 'light';
    setColorMode(newColorMode);
    htmlElement.className = newColorMode;
    window.localStorage.setItem('color_mode', newColorMode);
  };

  return (
    <div className="flex gap-1 py-5 border-b dark:border-dark-gray700 border-dark-gray300 justify-between items-center w-full cursor-pointer">
      <p className="dark:text-dark-gray100 text-black text-sm">
        다크 모드 전환
      </p>
      <Toggle onClick={handleChangeMode} toggle={colorMode === 'dark'} />
    </div>
  );
}

초기 로드 시 로컬 스토리지에서 저장된 모드를 가져와 colorMode 상태를 설정하고, 버튼 클릭 시 다크 모드와 라이트 모드를 전환합니다.

결론

Next.js와 Tailwind CSS를 사용하여 다크 모드와 라이트 모드를 구현하는 방법을 알아보았습니다. ThemeToggle 컴포넌트를 통해 사용자는 쉽게 모드를 전환할 수 있으며, 로컬 스토리지를 사용하여 설정을 유지할 수 있습니다.

profile
Frontend developer

0개의 댓글