🗺️

ReactでのdangerouslySetInnerHTMLによって生成されたHTMLにCSSを適用する方法

2023/08/23に公開

React(またはGatsby)を使用する際、コンポーネントに生のHTMLを挿入する必要があることがあります。これを実現する一般的な方法の一つは、dangerouslySetInnerHTMLを使用することです。しかし、CSSモジュールを使用している場合、この注入されたコンテンツにCSSを適用するのは少し難しいことがあります。この記事では、そのようなコンテンツのスタイリングに関する課題と解決策を説明します。

CSSモジュールの課題

CSSモジュールは、特定のコンポーネントにスタイルをスコープするためのReactアプリケーションでの一般的なアプローチです。これにより、グローバルな名前空間の汚染を防ぎ、スタイルの競合を回避することができます。しかし、dangerouslySetInnerHTMLを使用すると、内容が直接DOMに注入され、Reactによってレンダリングされないため、CSSモジュールスタイルを直接適用するのは難しいです。

例えば:

import styles from './myComponent.module.css';

// ...

<div className={styles.content} dangerouslySetInnerHTML={{ __html: myHTMLContent }} />

というコードで生成されるHTMLが

<div class="content">
  <h2 id="h0dd1f111">はじめに</h2>
  <div class="article-body">記事の紹介文・・・・・・</div>
  <h2 id="h0dd1f2323">論点</h2>
  <div class="article-body">論点の中身・・・・・・</div>
  <h2 id="h0dd1faaadfas">まとめ</h2>
  <div class="article-body">記事のまとめ・・・・・・</div>
</div>

だったとしましょう。この中の<h2>にまとめてスタイルを適用したいとします。その場合に少しコツが必要でした。

またCSSモジュールは衝突を避けるために一意のクラス名を生成するため、.contentを.content_1a2b3cのように変換し、スタイルが期待通りに適用されない可能性があります。

解決策: グローバルCSSの使用

dangerouslySetInnerHTMLを使用して挿入されたコンテンツをスタイルするための簡単な方法は、グローバルCSSを使用することです。

  1. グローバルCSSファイルの作成
    CSSモジュールの代わりに、global.cssなどのグローバルスタイルシートを作成します。
.content h2 {
    font-size: 1.3rem;
    font-weight: bold;
}
  1. グローバルCSSのインポート
    Gatsbyプロジェクトの場合、gatsby-browser.jsでスタイルシートをインポートします:
import './src/styles/global.css';

これにより、サイト全体でスタイルが利用可能になります。

  1. クラスを直接適用
    コンポーネント内で:
<div className="content" dangerouslySetInnerHTML={{ __html: content }} />

グローバルCSSを使用することで、dangerouslySetInnerHTMLを使用する際のCSSモジュールのスコープや命名の複雑さを回避し、スタイルを一貫して注入されたコンテンツに適用することができます。

まとめ

dangerouslySetInnerHTMLは、クロスサイトスクリプティング(XSS)攻撃などの潜在的なセキュリティリスクがあるため、慎重に使用する必要がありますが、必要な場合もあります。Reactでのそのようなコンテンツのスタイリングを考慮する際、スタイリングアプローチの性質を考慮することが重要です。グローバルCSSは、スタイルが注入されたコンテンツに一貫して適用されることを保証する簡単な解決策を提供します。

Discussion