「react-modal」を使ってモーダルウィンドウを実装

2024.07.13

Reactのライブラリの「react-modal」の使い方をメモしました。

ライブラリのドキュメントはこちら
作成するにあたってはこちらの記事を参考にさせていただきました。

react-modalを使ってModalコンポーネントを作る

react-modalは下記のコマンドによってインストールできます。
「cd」コマンドでプロジェクトまで移動し、インストールします。
TypeScriptで使う場合は型ファイルを取得しないとビルド時にエラーになるので注意してください。

npm install react-modal

//注意:TypeScriptの場合はこちら。
npm install -D @types/react-modal

これで準備完了です。

最もシンプルな状態

アニメーションもなく指定の箇所をクリックするとモーダルが開きます。
基本の使い方ですね。

import { useState } from 'react';
import Modal from 'react-modal';

Modal.setAppElement("#root");// アクセシビリティのために必要

export default function ModalBasic(){
  const [modalIsOpen, setIsOpen] = useState(false);

return (
    <>
      <button onClick={() => setIsOpen(true)}>モーダルを開く</button>
      <Modal
        isOpen={modalIsOpen}
        onRequestClose={() => setIsOpen(false)}
        closeTimeoutMS={500}
      >
        <button onClick={() => setIsOpen(false)}>閉じるボタン</button>
      </Modal>
    </>
  );
}

モーダルを開いてる時のスクリーンリーダーの制限

下記のコードについて

Modal.setAppElement("#root");

最初、サンプルサイトのこの記述の意味がわかりませんでした…。
こちらはmodalを開いてる時のスクリーンリーダー対応です。

目的は、スクリーンリーダーを使用するユーザーに対してモーダルが表示されている間は他のページコンテンツを読み上げないようにし、ユーザーがモーダル内の情報に集中できるようにするためです。

モーダルの開閉の処理

react-modalではコンポーネントタグに指定のpropsを記述することで様々な機能を実装することができます。
他にもpropsの種類はあるため、詳しくはドキュメントを見てもらえればと思います。

<Modal
  isOpen={modalIsOpen}
  onRequestClose={() => setIsOpen(false)}
  closeTimeoutMS={500}
>

「isOpen」はモーダルの開閉状態に関係しています。trueなら開き、falseなら閉じた状態です。

「onRequestClose」に実行する関数を指定すると、コンテンツ外の部分をクリックした際に閉じることができます。コンテンツ外とはモーダル表示でよくある背景黒塗り透過してる部分のことです。
今回指定している関数は開閉状態を管理するuseStateの「setIsOpen(false)」を使っています。

「closeTimeoutMS」はモーダルを閉じる動作を何秒後にするかを指定しています。閉じるボタンを押して0.5秒後にモーダルが閉じます。

開閉の状態管理はuseState()関数を使っています。

const [modalIsOpen, setIsOpen] = useState(false);

これによりモーダルの開閉状態を管理しています。

モーダルにアニメーションをつける。

今はボタンを押すとパッとモーダルが表示されてしまっています。何かしら動きが欲しいですね…

モーダルにアニメーションをつけるにはコンポーネントタグにCSSクラスを指定し、実際にCSSを書く必要があります。実際のブラウザでの表示は下記のようになります。

コードの方は下記のように変更。クラス名を色々記述しています。

export default function ModalBasic(){
  const [modalIsOpen, setIsOpen] = useState(false);

return (
    <>
      <button onClick={() => setIsOpen(true)}>モーダルを開く</button>
      <Modal
        isOpen={modalIsOpen}
        onRequestClose={() => setIsOpen(false)}
        overlayClassName={{
          base: "overlay-base",
          afterOpen: "overlay-after",
          beforeClose: "overlay-before"
        }}
        className={{
          base: "content-base",
          afterOpen: "content-after",
          beforeClose: "content-before"
        }}
        closeTimeoutMS={500}
      >
        <button onClick={() => setIsOpen(false)}>閉じるボタン</button>
      </Modal>
    </>
  );
}

モーダル開いてる際のオーバレイを定義する「overlayClassName」

オーバレイというのがわかりづらいですが、modalを開いた際によくある黒で透過された部分ですね。
このオーバレイ時に使用するCSSクラス名をそれぞれ定義してオブジェクトとして渡しているのが下記です。

overlayClassName={{
  base: "overlay-base",
  afterOpen: "overlay-after",
  beforeClose: "overlay-before"
}}

baseというはブラウザウィンドウ全体を覆う部分です。overlay-baseというクラスを定義しています。
overlay-afterはモーダルが開いてる時、overlay-beforeは閉じる際のアニメーションのために使っています。

次に定義したクラスにCSSを書きます。
なお、以下のCSSについては冒頭の参考サイト様よりCSSを使わせていただいています。
modalのそれぞれの状態に対してCSSのプロパティがあてられています。

.overlay-base {
  padding: 1rem;
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0);
  opacity: 0;
  transition-property: background-color, opacity;
  transition-duration: 500ms;
  transition-timing-function: ease-in-out;
  outline: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}

.overlay-after {
  background-color: rgba(0, 0, 0, 0.8);
  opacity: 1;
}

.overlay-before {
  background-color: rgba(0, 0, 0, 0);
  opacity: 0;
}

モーダル開いてる際のコンテンツ部分はclassNameで定義

先ほどがモーダル背景の透過部分でした。
今度はユーザーに見せたいコンテンツ部分のCSSです。

className={{
  base: "content-base",
  afterOpen: "content-after",
  beforeClose: "content-before"
}}

baseはコンテンツを表示している部分のクラス名。その名の通りのベース部分ですね。
content-afterはモーダルが開いてる際の表示とcontent-beforeはモーダルを閉じた時のアニメーションで使われています。

.content-base {
  position: relative;
  top: auto;
  left: auto;
  right: auto;
  bottom: auto;
  margin: 0 auto;
  border: 0;
  outline: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 0%;
  width: 0%;
  background-color: transparent;
  transition-property: background-color, width, height;
  transition-duration: 500ms;
  transition-timing-function: ease-in-out;
}

.content-after {
  width: 70%;
  height: 40%;
  background-color: rgba(250, 190, 190, 0.8);
}

.content-before {
  width: 0%;
  height: 0%;
  background-color: transparent;
}

baseとモーダルを開く前のbefore、モーダルを開いたafterにCSSを記述。
このようにしてモーダルの開閉の表示やアニメーションを制御しています。

totop Page Top