Tailwind CSSのダークモードでページを再読込した際のチラつきを解消する

公開日時

Tailwind CSSでダークモード対応をした際に、ダークモード状態でページを再読込みすると画面のチラつきが発生してしまった。

デフォルトのモードがlightモードになっており、useEffectでdark判定を行っているため、ページ読み込みから初回レンダリングが実行されるまでの間はlightモードが表示されてしまうのが原因。

気になるので何か手立てがないかと思って調べてみたところ、同様の現象に関するissueを発見。

Dark theme blinks on refresh · Issue #1995 · facebook/docusaurus

issueに記載されていた、「use-dark-mode」のREADMEを参考に public/noflash.js を追加し、ページ読み込み時にdark判定を行い、必要に応じてdark classを付与するように設定。

/* eslint-disable */
// Insert this script in your index.html right after the <body> tag.
// This will help to prevent a flash if dark mode is the default.

;(function () {
  var storageKey = 'theme'
  var classNameDark = 'dark'

  function setClassOnDocumentBody() {
    var html = document.getElementsByTagName('html')[0]
    html.classList.add(classNameDark)
  }

  var preferDarkQuery = '(prefers-color-scheme: dark)'
  var mql = window.matchMedia(preferDarkQuery)
  var supportsColorSchemeQuery = mql.media === preferDarkQuery
  var localStorageTheme = null
  try {
    localStorageTheme = localStorage.getItem(storageKey)
  } catch (err) {}
  var localStorageExists = localStorageTheme !== null

  if (localStorageExists) {
    if (localStorageTheme === classNameDark) {
      setClassOnDocumentBody()
    }
  } else if (supportsColorSchemeQuery) {
    setClassOnDocumentBody()
    localStorage.setItem(storageKey, classNameDark)
  }
})()

そして、bodyタグの直下に noflash.js 読み込みを追加する。

// pages/_document.tsx
import Document, { Html, Main, NextScript } from 'next/document'
import React from 'react'

export default class MyDocument extends Document {
  render() {
    return (
      <Html>
        <body className="dark:bg-gray-800 dark:text-gray-200">
          <script src="/noflash.js" />
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

これでダークモードで再読込しても画面のチラつきは発生しなくなった。

参考


Related #css

Youtube動画で学ぶTailwind CSS

「Designing with Tailwind CSS」シリーズがとても分かりやすかった。

tailblocks

tailwind cssのテンプレート集

Next.js 10 + Tailwind CSS 2.0 でAMP対応(hybrid)を行う

next/ampのhybridモードを使い通常ページとAMPページを生成し、PostCSSでCSSの容量削減を行いinline cssとして埋め込み

「Tailwind CSS Tips, Tricks & Best Practices」を観て学ぶ

動画を観ながら実際に手を動かして13個の練習問題を解いた