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?

react-modalを利用してハーフモーダルを実装する

Posted at

React-Modal を使ったハーフモーダルの実装方法

概要

この記事では、React のモーダルライブラリである react-modal を利用したハーフモーダルの実装方法を説明します。

実際の動作

preview.gif

この記事の対象者

  • React でハーフモーダルを実装したい人

react-modal について

react-modal とは、その名の通り React でモーダルを実装するためのライブラリです。

モーダルのロジックや UI を自作するのは意外と手間がかかりますが、このようなライブラリを使うことで、開発効率を向上させることができます。

実装

react-modal のインストール

まずは react-modal をインストールします。

npm install react-modal

Modal コンポーネントを利用した実装

続いて、react-modalModal コンポーネントを使用して、ハーフモーダルを実装します。

import { useCallback, useState } from "react";
import Modal from "react-modal";

function App() {
  const [isOpen, setIsOpen] = useState(false);

  const handleOpenModal = useCallback(() => {
    setIsOpen(true);
  }, []);

  const handleCloseModal = useCallback(() => {
    setIsOpen(false);
  }, []);

  return (
    <div className="container">
      <button type="button" onClick={handleOpenModal} hidden={isOpen}>
        Open Modal
      </button>
      <Modal
        contentLabel="halfModal"
        isOpen={isOpen}
        onRequestClose={handleCloseModal}
        className={{
          base: "modal-base",
          afterOpen: "modal-after",
          beforeClose: "modal-before",
        }}
        overlayClassName={{
          base: "overlay-base",
          afterOpen: "overlay-after",
          beforeClose: "overlay-before",
        }}
        closeTimeoutMS={250}
      >
        <div className="modal-inner">
          <p>モーダルの中身</p>
          <button type="button" onClick={handleCloseModal}>
            Close Modal
          </button>
        </div>
      </Modal>
    </div>
  );
}

export default App;

props の説明

プロパティ 説明
isOpen モーダルの開閉状態を管理する state
onRequestClose モーダル外をクリックしたときに発火する関数
className モーダルのクラス名
overlayClassName モーダル背景のクラス名
closeTimeoutMS モーダルの開閉時のアニメーション時間

CSS の設定

.modal-base {
  width: 100%;
  height: calc(100vh - 50px);
  background-color: green;
  overflow-y: auto;
  border-radius: 12px 12px 0 0;
  transition: all 250ms ease-in-out;
  transform: translateY(100%);
}

.modal-after {
  transform: translateY(0%);
}

.modal-before {
  transform: translateY(100%);
}

.modal-inner {
  color: #fff;
  text-align: center;
}

.overlay-base {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: end;
  transition: background-color 250ms ease-in-out;
}

.overlay-after {
  background-color: rgb(0 0 0 / 0.8);
}

.overlay-before {
  background-color: rgb(0 0 0 / 0);
}

実際のコードと挙動

CodeSandbox でデモを見る

実装の注意点

1. フォントが適用されない問題

react-modalModal コンポーネントは、DOM ツリーでは <div id="root" /> の外側に挿入されます。
そのため、#root に対してフォントを指定している場合、モーダル内のコンテンツにはフォントが適用されないことがあります。

解決策

.modal-base などにフォントを明示的に指定することで適用できます。

.modal-base {
  font-family: "Arial", sans-serif;
}

2. モーダル表示時の背景スクロール問題

react-modal は、モーダル表示時に背景スクロールを固定しません。そのため、モーダル内をスクロールしようとすると、背景もスクロールされる問題が発生します。

解決策

useEffect を利用して、モーダルが開いている間は bodyoverflowhidden にすることで対応できます。

import { useEffect } from "react";

useEffect(() => {
  document.body.style.overflow = isOpen ? "hidden" : "auto";
  return () => {
    document.body.style.overflow = "auto";
  };
}, [isOpen]);

まとめ

本記事では、react-modal を利用したハーフモーダルの実装方法について説明しました。

  • react-modal の基本的な使い方
  • classNameoverlayClassName を利用したアニメーションの実装
  • モーダル特有の注意点(フォント問題・スクロール制御)

ハーフモーダルは、スマホアプリのようなUIを作成する際に役立つので、ぜひ活用してください!

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?