【CSS+JS】メニューアイコンの一種、ベントーメニューの実装方法(アニメーション付き)

はじめに

メニューアイコンの中ではハンバーガーメニューが有名だと思いますが、その他にもいろいろな種類があって、それぞれに名前もつけられています。

本記事では、ハンバーガーメニューの次に比較的よく使われているであろうベントーメニューの実装方法について説明します(クリックしたときのいい感じのアニメーションについても説明します)。

なお、メニューアイコン(ハンバーガーメニュー)の基本的な実装方法については以下の記事で詳しく説明しています。

サンプル

右上のベントーメニューをクリックすると、9つのドットが回転しつつバツマークに変化します。

実装

HTML

JavaScriptを使わずにメニューアイコンを実装するにはチェックボックスを使います。

9つのドットはそのままdivタグを9つ並べています。この他にも#dots-wrapで囲んだり、3つごとに.dots-rowで囲んだり、様々な方法があるかと思いますので、ご自分の好きなように並べてください。

<header>
  <input id="navi" type="checkbox" />
  <label for="navi">
    <div class="dots">
    <div class="dots">
    <div class="dots">
    <div class="dots">
    <div class="dots">
    <div class="dots">
    <div class="dots">
    <div class="dots">
    <div class="dots">
  </label>
</header>

CSS

CSSは少し長いので、label(9つのドット)と#navi(クリック時のアニメーション)に分けて説明します。

SCSS

header {
  width: 100%;
  height: 80px;
  #navi {
    display: none;
    &:checked {
      ~ label {
        transform: rotate(225deg);
        .dots:nth-of-type(1) { filter: opacity(0); }
        .dots:nth-of-type(2) { transform: scaleY(4.75); }
        .dots:nth-of-type(3) { filter: opacity(0); }
        .dots:nth-of-type(4) { transform: scaleX(4.75); }
        .dots:nth-of-type(5) { filter: opacity(0); }
        .dots:nth-of-type(6) { transform: scaleX(4.75); }
        .dots:nth-of-type(7) { filter: opacity(0); }
        .dots:nth-of-type(8) { transform: scaleY(4.75); }
        .dots:nth-of-type(9) { filter: opacity(0); }
      }
    }
  }
  label {
    cursor: pointer;
    position: fixed;
    top: 32px;
    right: 32px;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-content: space-between;
    width: 26px;
    height: 26px;
    transition: .5s;
    .dots {
      width: 6px;
      height: 6px;
      background-color: black;
      transition: .5s;
      &:nth-of-type(3n+2) {
        margin: 0 4px;
      }
      &:nth-of-type(2) { transform-origin: top; }
      &:nth-of-type(4) { transform-origin: left; }
      &:nth-of-type(6) { transform-origin: right; }
      &:nth-of-type(8) { transform-origin: bottom; }
    }
  }
}

9つのドット

SCSS

  label {
    cursor: pointer;
    position: fixed;
    top: 32px;
    right: 32px;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-content: space-between;
    width: 26px;
    height: 26px;
    transition: .5s;
    .dots {
      width: 6px;
      height: 6px;
      background-color: black;
      transition: .5s;
      &:nth-of-type(3n+2) {
        margin: 0 4px;
      }
      &:nth-of-type(2) { transform-origin: top; }
      &:nth-of-type(4) { transform-origin: left; }
      &:nth-of-type(6) { transform-origin: right; }
      &:nth-of-type(8) { transform-origin: bottom; }
    }
  }

まず、9つのドットを囲むlabelの横幅および縦幅は「ドットの大きさ×3+ドット間の余白×2」の値にします。例えば、ドットの大きさが6pxでドット間の余白が4pxの場合、6×3+4×2=26が横幅および縦幅になります。ドットの大きさやドット間の余白を変更する場合はlabelの大きさも調節してください。

また、labelをフレックスボックスにし、justify-contentalign-contentspace-betweenに設定することで、9つのドットが均等に配置されるようにしています。

左上から数えて2,4,6,8番目のドットはアイコンクリック時のアニメーションで変化させるので、それぞれtransform-originの値を設定しておきます。

クリック時のアニメーション

SCSS

  #navi {
    display: none;
    &:checked {
      ~ label {
        transform: rotate(225deg);
        .dots:nth-of-type(1) { filter: opacity(0); }
        .dots:nth-of-type(2) { transform: scaleY(4.75); }
        .dots:nth-of-type(3) { filter: opacity(0); }
        .dots:nth-of-type(4) { transform: scaleX(4.75); }
        .dots:nth-of-type(5) { filter: opacity(0); }
        .dots:nth-of-type(6) { transform: scaleX(4.75); }
        .dots:nth-of-type(7) { filter: opacity(0); }
        .dots:nth-of-type(8) { transform: scaleY(4.75); }
        .dots:nth-of-type(9) { filter: opacity(0); }
      }
    }
  }

ベントーメニューのアイコンをクリックするとチェックボックスのチェック状態が切り替わります。チェックボックスの:checkedにスタイルを設定することでアイコンクリック時にアニメーションを設定することができます。

設定するアニメーションは以下の通りです。

  • 全体(label)を225°回転させる
  • 奇数番目のドット(.dots:nth-of-type(1,3,5,7,9))を透明にする
  • 偶数番目のドット(.dots:nth-of-type(2,4,6,8))を中央へ拡張する

ベントーメニューのクリック時のアニメーションは様々な種類があります。本記事の内容を参考にしていろいろなアニメーションを試していただければと思います。

まとめ

ベントーメニューとは日本語の「弁当」から来ているのでしょうね。四角い弁当箱におかずが詰め込まれている様子によく似ています。外国には日本のような弁当文化がないので、外国でも日本語の「弁当」という言葉が定着していることが伺えます。

本記事の内容を参考にして、ベントーメニューを実装していただければと思います。

関連記事

【CSS+JS】メインコンテンツの裏から現れるフッターの実装方法
# はじめに オシャレなサイトなどでたまに見かける「メインコンテンツの裏から現れるフッター」の実装方法について説明します。 # サンプル <iframe height="392" style="width: 100%;" scrollin [...]
2021年10月18日 13:26
【CSS+JS】背景画像の視差効果(パララックス)を実装する方法
# はじめに JavaScriptプラグインを使わずに、背景画像の視差効果(パララックス)をVanilla JS(ピュアなJavaScript)だけで実装する方法について説明します。 # サンプル まず、背景画像の視差効果(パララックス) [...]
2021年10月17日 12:08
【CSS+JS】ウィンドウ内全体にファイルをドラッグ&ドロップしてアップロード
# はじめに ユーザーが選択したファイルをアップロードする必要がある場合、ファイル選択フィールドを設置することはもちろんですが、ファイルをドラッグ&ドロップしてアップロードできるようにもなっていると使い勝手のいいサービスだと言えます。しかし、ドラ [...]
2021年6月2日 15:15
【CSS+JS】モーダルウィンドウを表示しその中にYouTube動画を動的に埋め込む
# はじめに 動画のサムネイル画像をクリックしてモーダルウィンドウを表示し、その中にYouTube動画を動的に埋め込む方法について説明します。なお、本記事ではYouTube動画を動的に埋め込むまでを範囲とし、埋め込んだ動画の再生制御などは範囲外と [...]
2021年5月20日 23:23
【CSS+JS】テキストを1文字ずつ表示するアニメーションの実装方法
# はじめに モダンなサイトでよく見かける「テキストを1文字ずつ表示するアニメーション」の実装方法を解説します。 # 実装 ## サンプル 繰り返し動作を確認したい場合は右下の「Rerun」ボタンをクリックしてください。 <i [...]
2021年5月20日 13:26
【CSS】CSSだけでMarkdownのコードにファイル名をつける
# はじめに Markdownのコードに、そのコードがどのファイルのものなのかを示すためにファイル名が書いてあるとわかりやすいです。以下はQiitaの記事でコードを書いたときの一例です。 <img data-src="https://i.i [...]
2021年4月6日 14:39
【CSS】カーソルを乗せると流れるようなアニメーションのハンバーガーメニューを作る
# はじめに 今回はハンバーガーメニューにカーソルを乗せると川のように流れるアニメーションを作りたいと思います。 今回の記事は以下の記事をベースにしていますので、まだご覧になっていない方は先にこちらをご覧ください。 <div clas [...]
2020年8月31日 8:54
【CSS】JavaScriptを使わずにハンバーガーメニューを作る
# はじめに 当初はスペースの限られるスマートフォンなどの低解像度デバイス向けサイトにおいてスペースを有効活用するために登場したハンバーガーメニューですが、最近はPCなどの高解像度デバイス向けサイトでも使われているのをよく見かけます。 何よ [...]
2020年8月31日 7:34