Next.jsブログでzenn-markdown-htmlのダークモード対応を実装する

公開日:
目次

Next.jsブログでzenn-markdown-htmlを使っていて、ダークモードでテーブル(表)が見づらい問題を解決したので備忘録を残します。

zenn-markdown-htmlのダークモード問題

Next.jsとnext-themesでダークモード切り替えを実装していましたが、zenn-markdown-htmlで変換したmarkdown内のテーブルがダークモードでも白背景のままで、非常に見づらい状態でした。

コードブロックの背景は元々ダークブルーだったので問題なかったのですが、表だけが白く浮いてしまっていました。

zenn-markdown-htmlのダークモード対応

2025年5月にzenn-markdown-htmlがv0.1.160でダークモードに対応しました。

data-theme属性を使ってテーマを切り替えることができるようになっています。

この機能を使うことで、markdownコンテンツ内の表などがダークモードに適切に対応できるようになりました。

実装手順

パッケージのアップデート

まず、zenn関連パッケージを最新版にアップデートします。

npm update zenn-markdown-html zenn-content-css zenn-embed-elements

バージョン0.1.160以降が必要です。確認するには以下のコマンドを実行します。

npm list zenn-markdown-html zenn-content-css zenn-embed-elements

markdownコンテンツにdata-theme属性を追加

markdownコンテンツを表示している部分で、zncクラスがついた要素にdata-theme属性を追加します。

// 基本的な実装例
const { theme } = useTheme()

// markdownコンテンツを表示する部分
<div className="znc" data-theme={theme === 'dark' ? 'dark-blue' : 'light'}>
  <div dangerouslySetInnerHTML={{ __html: markdownContent }} />
</div>

next-themesを使っている場合のハイドレーションエラー対策も含めた実装は下記の通りです。

import { useTheme } from 'next-themes'
import { useEffect, useState } from 'react'

const MarkdownRenderer = ({ content }: { content: string }) => {
  const { theme } = useTheme()
  const [mounted, setMounted] = useState(false)

  useEffect(() => {
    setMounted(true)
  }, [])

  if (!mounted) {
    return <div className="znc" dangerouslySetInnerHTML={{ __html: content }} />
  }

  return (
    <div className="znc" data-theme={theme === 'dark' ? 'dark-blue' : 'light'}>
      <div dangerouslySetInnerHTML={{ __html: content }} />
    </div>
  )
}

コード解説

data-theme属性

zenn-content-cssは以下のテーマをサポートしています:

  • light: ライトモード(デフォルト)
  • dark-blue: ダークモード

zncクラスが付いた要素にdata-theme属性を設定することで、その配下のコンテンツのテーマが切り替わります。

next-themesとの連携

useThemeフックでnext-themesの現在のテーマを取得し、それに応じてdata-themeを切り替えています。

ハイドレーションエラー対策

const [mounted, setMounted] = useState(false)

useEffect(() => {
  setMounted(true)
}, [])

if (!mounted) {
  return null
}

この部分はSSRとクライアントサイドでのテーマの不一致によるハイドレーションエラーを防ぐための処理です。

これでmarkdownコンテンツもダークモードに対応し、テーブルが暗い背景と境界線で適切に表示されるようになりました。

参考