🙌

React Modalをnextjs&cssModule環境で使う

2022/08/10に公開1

目的

  • チーム開発で共通的にReact Modalを使いたい

アニメーションで行き詰まる & 解決

  • モーダルをふわっと出すなど、アニメーションを実装する際に詰まりました
  • 公式ページを見るとCSS貼り付ければOKという感じで書いてあるのですが、それだと詰まりました
  • 参考

行き詰まったこと

私の環境では素直にcssのクラスが当てはまらなくて困りました
原因は、cssModuleをpostCssでビルドしてクラス名をハッシュ化、
それをtsxで使っていたためです

.ReactModal__Overlay {
    opacity: 0;
    transition: opacity 2000ms ease-in-out;
}

.ReactModal__Overlay--after-open {
    opacity: 1;
}

.ReactModal__Overlay--before-close {
    opacity: 0;
}

ビルドされて例えば以下のようになり、React Modalの既存クラス名と不一致

.ReactModal__Overlay--hobaXFASDFA124 {
    opacity: 0;
    transition: opacity 2000ms ease-in-out;
}
...

ReactModal__Overlay--hobaXFASDFA124このクラス名ではReact Modal内の既にあるクラスに対して当てはまりません
なので直接cssModuleをReactModalに埋め込む方法を探りました
するとclassNameプロパティに拡張がありそうだったのでこちらを利用して解決しました

  <Modal
    {...}
    className={{
      base: cssModule['ReactModal__Overlay'],
      afterOpen: cssModule['ReactModal__Overlay--after-open'],
      beforeClose: cssModule['ReactModal__Overlay--before-close']
    }}
  >
    <h2>Add modal content here</h2>
  </Modal>

classNameにオブジェクト定義をすることで、base, afterOpen, beforeCloseのタイミングで付与することができます
こちらを使ってアニメーションを実現することができました


アニメーションの実装

  • ふわっとモーダルを表示することができたので、次は下からスライドしてくるモーダル を作りたい
    参考

スライドするモーダルを作る上で知っておいた方が良さそうなもの

  • @keyframes
  • transform: translate
  • animation

@keyframes

  • 参考
  • transitionが始点と終点の間の変化をデザインするものだとすると、@keyframesその中間地点もカスタマイズすることができるもの
@keyframes identifier {
  0% { top: 0; }
  50% { top: 30px; left: 20px; }
  50% { top: 10px; }
  100% { top: 0; }
}

transform/translate

  • 参考
  • transformの種類としてtranslateがある(役割は移動)
  • transformは:hoverや動的につけられたclassに対して付与して変化の制御をする
  • transitionはルートとなるクラスに対して変更の速度や間隔を制御する

animation

  • 参考
  • スタイル間のアニメーションを適用するもの
  • transitionよりもアニメーションに特化したプロパティのように思えました

コード

@keyframes k-slideup {
  from {
    transform: translate(-50%, -1%);
    opacity: 0;
  }
  to {
    transform: translate(-50%, -50%);
    opacity: 1;
  }
}
@keyframes k-slidedown {
  from {
    transform: translate(-50%, -50%);
    opacity: 1;
  }
  to {
    transform: translate(-50%, -1%);
    opacity: 0;
  }
}

&__content {
  opacity: 0;
  transition: opacity 500ms ease-in-out;
}
&__content--after-open{
  animation: k-slideup .5s ease-in-out forwards;
}
&__content--before-close{
  animation: k-slidedown .5s ease-in-out forwards;
}

まとめ

  • transformプロパティを使うと、position:fixedが効かなくなり、モーダル時のスクロールの際に、ヘッダーの固定などができなくなる問題に直面
  • 残課題はあるが一旦アニメーション自体は上記の方法でできた

Discussion