🍔

【CSS】ハンバーガーメニューの基本

2024/03/04に公開

ハンバーガーメニューの基本的な作成方法のメモ書きです。

他に良いやり方が色々あると思いますが、学んだ方法を書き留めておきます。

結果

全体の流れ

ハンバーガーメニューをクリックしたら、jsで関数を実行し、htmlタグにopenクラスが追加されます。このクラスの有無によって、CSSでデザインを変えています。

HTML

<body>

    <div class="content">

        <nav class="nav">
            <ul>
                <li><a href="#">ハンバーガー</a></li>
            </ul>
        </nav>
      
      <h2 class="text">右のボタンをクリック→</h2>

        <button type="button" class="nav-button" onclick="navFunc()">
            <!-- スクリーンリーダー用のテキスト -->
            <span class="sr-only">MENUボタン</span>
        </button>
    </div>

</body>
  • buttonタグに「onclick」を設定し、クリックされた際、JSの関数を実行する処理をしています
  • スクリーンリーダーという「画面の表示内容を音声で読み上げるソフト」を使用している人のためのテキストを追加しています。これは、無くても動作します。

CSS

CSSは行が長いの、分けて説明

基本設定

@charset "UTF-8";

/* 変数 */
:root {
    /* 色 */
    --button: #222222;
}

:root.open {
    --button: #ffffff
}

a {
    color: inherit;
    text-decoration: none;
}

a:hover {
    opacity: 0.8;
}
  • .openクラスがある場合は、ハンバーガーボタンの色を変化させています
  • aタグの下線を消し、liタグの色で変化するようにしています
  • aタグホバー時は、少し透明にしています
/* 基本設定 */
body {
    font-size: 16px;
    line-height: 1.8;
    margin: 0;
    height: 100vh;
}

h2 {
    margin-top: 10px;
}
  • bodyの大きさを画面全体に設定
  • 余分なマージンの除去
  • h2は、ハンバーガーメニューボタンとのズレ調整
/* コンテンツの設定 */
/* ハンバーガーメニューを右上に表示させる */
.content {
    display: flex;
    justify-content: end;
    align-items: start;
    text-align: center;
    height: 100%;
}

/* スクリーンリーダー用のテキストを非表示 */
.sr-only {
    border: 0;
    position: absolute;
    clip: rect(0 0 0 0);
    height: 1px;
    width: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
}
  • ハンバーガーメニューを右上に配置しています。
  • スクリーンリーダーのテキストを非表示にしています。
  • absoluteに設定し、幅を持たせないようにしています。

ボタンの作成

/* ナビゲーションボタン */
.nav-button {
    box-sizing: content-box;
    padding: 0px;
    margin: 20px;
    border: none;
    outline: none;
    background: none;
    width: 40px;
    height: 30px;
    cursor: pointer;
    color: var(--button);
}

.nav-button::before,
.nav-button::after {
    content: '';
    display: block;
    height: 2px;
    background-color: currentColor;
    transform: translateY(15px);
    transition: 0.3s ease-in-out;
}

.nav-button::before {
    transform: translateY(-15px);
    box-shadow: 0 15px currentColor;
}
  • メニューを開くボタンの作成

  • border・padding・outline・background といったボタンにデフォルトで値が入っているプロパティを除去

  • マージンで、表示位置の調整

  • widthで横幅の指定、ボタンの線の幅も変更される

  • heightで高さ指定、ボタンの間隔は変わらない

    • ボタンの間隔を変更する場合は、以下の[ ]内の値を変更する

      transform: translateY([15px]);
      
      transform: translateY([-15px]);
      box-shadow: 0 [15px] currentColor;
      
  • cursorでカーソルを合わせたときの設定

  • colorで変数( —button )を設定

    • .openクラスがある場合に、色を変更するため
  • .nav-button::before, ::after

    • heightは線の太さを指定
    • display: block; で描画
    • transitionで「ボタンの開閉」に応じたアニメーションを設定
  • .nav-button::before

    • box-shadowで真ん中の線を描画している
/* ナビゲーションメニュー:(閉じるボタン) */
.open .nav-button {
    z-index: 1000;
}

.open .nav-button::before {
    transform: rotate(-45deg);
    box-shadow: none;
}

.open .nav-button::after {
    transform: rotate(45deg);
    box-shadow: none;
}
  • メニューを閉じるボタンの作成
  • z-indexで一番上に表示されるように指定
  • transform: rotate()で✕ボタンを作成している

ナビゲーションメニューの表示

/* ナビゲーションメニュー:(閉じた状態) */
.nav {
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    width: 0;
    height: 0;
    left: 100%;
    overflow: hidden;
    color: transparent;
    transition: 0.5s ease-in-out;
}
  • 閉じた状態のとき
  • display、justify-content、 align-itemsを指定し、表示の不具合を防ぐ
    • 指定しないと、テキストが左上に移動してから閉じるというアニメーションになる
  • position、left、overflow、colorでテキストを画面外に出し、見れないようにしている
  • absoluteで要素の大きさを他の要素に影響しないようにしている
  • transitionでアニメーションを設定
/* ナビゲーションメニュー:(開いた状態) */
.open .nav {
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.8);
    color: #ffffff;
}

.nav ul {
    margin-bottom: 10vh;
    list-style: none;
}

.nav li:not(:last-child) {
    margin-bottom: 20px;
}
  • ナビゲーションを表示している画面の設定
  • .open .navクラスでテキストを表示している
  • ulでリストの「・」を削除し、テキストの位置を調整
  • li:not(:last-child) でテキストの幅を調整している

JavaScript

function navFunc() {
    document.querySelector('html').classList.toggle('open')
}
  • htmlタグにopenクラスが無ければ追加し、あれば削除する処理

参考資料


https://ep.ebisu.com/practice02/

↓ スクリーンリーダーの説明
https://wa3.i-3-i.info/word11639.html

Discussion