Tailwind CSS でダークモードに対応する


こんにちは。Gaji-Labo 横田です。今日は Tailwind CSS でのダークモード対応について紹介します。

:dark を使う

Tailwind CSS では、ダーク モードが有効な時、ダークモードでスタイルを変更できる機能が用意されています。
以下のように dark: でプロパティを指定するだけなので簡単ですね。

<div class="bg-white dark:bg-slate-900">
  <h1 class="text-slate-900 dark:text-white">Title</h1>
  <p class="text-slate-900 dark:text-white">
    Text
  </p>
</div>

デフォルトでは、CSS の prefers-color-scheme で取得された設定値によって自動切り替えしているので、コード例の場合、ユーザーのシステム環境が明色テーマであれば bg-white text-slate-900 が反映され、暗色テーマであれば bg-slate-800 text-white が反映されます。

:dark 使用のメリットとデメリット

導入コストがかからず簡単に利用できることが最大のメリットな反面、サイト全体でライトモードとダークモードの色指定を併記して指定する必要があるので、コードが冗長になること、メンテナンス性に欠けることがデメリットと言えそうです。
また、ライトモード用 light: のような機能は用意されておらず、 dark: のみで色指定するとユーザーの環境が明色テーマであれば色が反映されないので、デフォルトのデザインが暗色テーマで後からライトモードを追加したいようなケースでも、コード例のように必ず色の併記が必要になります。

コードの冗長性というデメリットを解決できそうな方法のひとつとして、@apply でカスタムスタイルを作る手法は考えられます。

@layer components {
  .text-color {
    @apply text-gray-900 dark:text-white;
  }
}
<p class="text-color">
    Text
</p>

一見実装コストが下がったように見えますが、この方法では、.text-color で指定したスタイルを開発者が把握していないと、以下のように色を重複して指定してしまうことが起きるでしょう。

<p class="text-color text-stone-500">
    Text
</p>

通常はエディタに Tailwind CSS Intellisense を導入していると、色などスタイルが競合している箇所に警告を出してくれるのですが、カスタムスタイルを使っていると警告が出ないので、色が重複していることに気づかずバグリスクが生まれます。
ダークモード実現のためだけに @apply の使用は避けたほうがよさそうです。
@apply の使いどころは以下も参考にしてください)

CSS変数とカスタムカラーを使う

:dark を使用せず、ダークモードを手動で切り替えて、CSS変数とカスタムカラーの組み合わせを使う方法も紹介します。まず、CSS変数でダークモードとライトモードの色を定義します。

@layer base {
  :root {
    /* ライトモードの色定義 */
    /* 色の透過を調整できるようカラーチャネルで指定 */
    --background: 255 255 255;
    --text: 0 0 0;
  }

  .dark {
    /* ダークモードの色定義 */
    --background: 0 0 0;
    --text: 255 255 255;
  }
}

次に tailwind.config でダークモードを class によって切り替え、カスタムカラーを先ほど指定したCSS変数で追加します。

// ...
module.exports = {
  darkMode: 'class',
  // ...
  theme: {
    extend: {
      backgroundColor: {
        hoge: 'rgb(var(--background))',
      },

      textColor: {
        fuga: 'rgb(var(--text))',
      },
    },
  },
};

この設定で、以下のように dark class とカスタムカラーを指定することでダークモード指定ができます。

<html class="dark">
<div class="bg-hoge">
      <p class="text-fuga">
        Text
      </p>
  </div>
</html>

この方法では dark class をスイッチングさせる実装は別途必要になりますが、コードが冗長にならず、色を一元管理できることでメンテナンス性が上がることがメリットです。

終わりに

Tailwind CSS のダークモード対応は、ユーザーに任意でスイッチングを選択させたいのか、システムの設定値によって自動切り替えしたいのか、サイトの規模感、実装コストとのバランスによって対応方法のベストな選択が変わってくると思います。参考になれば幸いです。

Gaji-Laboでは、React経験が豊富なフロントエンドエンジニアを募集しています

弊社ではReactの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!

投稿者 Yokota Tomoko

運用やアクセシビリティに配慮したHTML/CSSの設計やコンポーネント作成、スタイルガイドの構築、コードレビュー、組み込み、要件の整理、社内進行管理、顧客とのコミュニケーションまで、ジョインしたチームを前に進めるためにあれこれ担当しています。子育てと仕事のバランスを楽しめるよう、日々模索しています。