🔖

CSSアニメーションで画面下部からスライドインするアニメーションを実装する

2023/04/15に公開

概要

CSSのアニメーションを使って、画面の最下部からスライドアップのアニメーションでメニューを表示する方法について紹介します。

イメージとしては、以下のような初めから表示されているメニューの開閉ボタンを押下すると、画面外に隠れていたサブメニューが表示される。というものです。

[イメージ]

コード

React + TypeScriptを使って記載したコードは以下のようになります。

Reactコンポーネント

import { useState } from "react";
import "./styles.css";

export default function App() {
  const [showSubMenu, setShowSubMenu] = useState(false);
  return (
    <div className="room">
      <div className="content">Main Content</div>

      <div className="menu-wrapper">
        <div className={`sub-menu-wrapper ${showSubMenu ? "show" : ""}`}>
          <div className="sub-menu">Menu</div>
        </div>
        <div className="menu">
          <button type="button" onClick={() => setShowSubMenu((prev) => !prev)}>
            Open Menu
          </button>
        </div>
      </div>
    </div>
  );
}

CSS

.room {
  position: relative;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.content {
  width: 100%;
  height: 100%;
  overflow-y: scroll;
  flex-grow: 1;
  background-color: aqua;
  display: flex;
  flex-direction: column;
}

.menu-wrapper {
  background-color: aqua;
}

.menu {
  position: relative;
  height: 100px;
  background-color: coral;
  z-index: 100;
}

.sub-menu {
  height: 300px;
  background-color: darkgreen;
}

.sub-menu-wrapper {
  width: 100%;
  height: 0;
  transform: translateY(100%);
  transition: transform 0.25s, height 0.25s;
  overflow: hidden;
}

.sub-menu-wrapper.show {
  height: 300px;
  transform: translateY(0);
}

実装しているメインのアニメーションでは、表示したいサブメニューを予め transform: translateY(100%) でメニューの裏側に隠しておき、ボタンが押されたタイミングで translateY(0) に変更しています。

ポイントとしては、 sub-menu-wrapper の高さを非表示時には0に設定し、この高さもアニメーションでサブメニューの高さに変更しています。
また sub-menu-wrapperoverflow: hidden; を設定しています。

この実装の理由は、サブメニューが position: absolute; を使わずにメニューの上に表示される要素であり、高さを0にしておかないと画面からはみ出してしまうからです。

position: absolute を使わない方法で実装している理由は、メニューの上に相対的に別のボタンを配置したいという要件があるためです。今回の方法では、サブメニューが表示されていればサブメニューの上に、サブメニューが非表示であればメニューの上にボタンを表示することが簡単にできることから、このような実装を選択しました。

実際のコードは以下になります。

以上、誰かの参考になれば幸いです。

Discussion