0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Bootstrap.cssを特定の領域内部のみに適用し、その中にReactのコンポーネントを描画する方法(ShadowDOMを利用)

Last updated at Posted at 2025-01-02

はじめに

既存のWebサイトにReactのコンポーネント(react bootstrap)を描画しようとしたところ、bootstrap.cssを読み込む必要があり画面全体のレイアウトが崩れてしまいました

そこで、Reactのコンポーネントを描画するElementのみにbootstrap.cssを適用するため、ShadowDOMを利用してCSSのスコープを独立させてみます

1. createRootを使用してReactのコンポーネントをShadow DOMにレンダリングします

ScopedStyleArea.tsx
import React, { useEffect, useRef } from 'react';
import ReactDOM from 'react-dom/client';

type ScopedStyleAreaProps = {
  children: React.ReactNode,
  styleSheets?: string[],
}
/**
 * スタイルシートを特定の領域のみに反映させ、更にその中にReactのコンポーネントを配置するためのコンポーネント
 * ・適用するスタイルシートはpropsで引き渡す
 *    <ScopedStyleArea styleSheets={['/bootstrap.min.css', '/other.css']}>
 *      <Button>Button Component</Button>
 *    </ScopedStyleArea>
 */
const ScopedStyleArea: React.FC<ScopedStyleAreaProps> = ({ children, styleSheets }) => {
  const containerRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    if (containerRef.current) {
      // Shadow DOMを作成
      const shadowRoot = containerRef.current.shadowRoot || containerRef.current.attachShadow({ mode: 'open' });

      // Shadow DOM内にReactコンポーネントをレンダリング
      const shadowRootElement = document.createElement('div');
      shadowRoot.appendChild(shadowRootElement);

      const root = ReactDOM.createRoot(shadowRootElement);
      root.render(
        <>
          {/* CSSの適用 */}
          {styleSheets?.map((sheet) => (
            <link key={sheet} rel="stylesheet" href={sheet} />
          ))}
          {children}
        </>
      );
    }
  }, [children, styleSheets]);

  return <div ref={containerRef} />;
};

export default ScopedStyleArea;

2. 利用方法

  • ScopedStyleAreaを使ってReactのコンポーネントをShadow DOM内でレンダリングします
  • 適用するcssをstyleSheetsに指定します
App.tsx
import {Button} from 'react-bootstrap';
import ScopedStyleArea from './ScopedStyleArea';

function App() {
  return (
    <ScopedStyleArea styleSheets={['/bootstrap.min.css', '/other.css']}>
      <Button>Button Component</Button>
    </ScopedStyleArea>
  )
}

export default App

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?