【Bootstrap5 テンプレート】サイドメニュー(縦メニュー)の作成:非表示機能付き

時計 2022.02.09 / 時計

【Bootstrap5 テンプレート】サイドメニュー(縦メニュー)の作成:非表示機能付き

本記事ではBootstrap5を使用したサイドメニュー(縦メニューバー)の作成方法について解説していきます。

仕事で利用するようなWebアプリケーションでは縦型のサイドメニューを利用することが多いです。

しかし画面上部にある横メニューの作成方法はよく見かけますが、縦型のサイドメニューの作成方法はなかなかWeb上では見かけません。

そこでテンプレートの作成を通してサイドメニューの作成について解説していきます。

またサイドメニューはボタンの押下で表示・非表示する機能をJavaScriptで追加します。

作成するテンプレート

本記事で作成するBootstrap5によるWebアプリケーション用テンプレートは次図のようになります。

Bootstrap5:テンプレート(サイドメニュー)

三本線のボタンを押すことでサイドメニューが非表示になります。

Bootstrap5:テンプレート(サイドメニューの非表示)

それでは次項よりこのテンプレートの作成方法を一つずつ解説していきます。

ページの高さを画面いっぱい(100%)にする

ここで作成するページは高さが画面いっぱい(100%)にして、スクロールがbody要素上で行われないようにします。

そのためhtml要素とbody要素にSizingユーティリティの高さ設定のクラスであるh-100クラスを追加します。

<html class="h-100">
    <body class="h-100">
    <!— ヘッダー -->
    <!— サイドメニュー -->
    <!— メインコンテンツ -->
    </body>
</html>

h-100クラスを追加することにより以下のcssが適用されます。

hight: 100%!important

高さではなく横幅を指定する場合はw-100などを利用します。

header要素の設定

header要素

テンプレート上のサイトタイトルやLoginや新規登録のリンクを入れ込むheader部を作成します。

hearder要素を以下のようにbody要素の間に記入します。

<html class="h-100">
    <body class="h-100">
        <header class="w-100 d-flex justify-content-between align-items-center bg-light px-3">
            <!— ヘッダーの内容 -->
        </header>
        <!— サイドメニュー -->
        <!— メインコンテンツ -->
    </body>
</html>

header要素には以下のクラスを指定しています。

  • w-100
  • d-flex
  • justify-content-between
  • align-items-center
  • bg-light
  • px-3

d-flexクラスはflexbox(フレックスボックス)を有効にします。d-flexクラスを指定された要素はflexコンテナとなり、その子要素はflexアイテムとなります。

display: flex !important;

子要素のflexアイテムを垂直方向に中央揃えするためにalign-items-center、flexアイテムを両端に配置するためにjustify-content-betweenを追加しています。

高さを固定するために高さを50pxに設定し、影を付けるためcssファイルに以下を追加します。

header{
  height: 50px;
  box-shadow: 0px 0px 5px 0px hsla(0, 0%, 7%, 0.3);
}

ヘッダー内部

header要素の内部に以下コードを記述します。

<ul class="navbar-nav d-flex flex-row">
    <li class="nav-item mx-3 text-muted active"><a href="#" class="nav-link text-secondary">New</a></li>
    <li class="nav-item mx-3 text-muted"><a href="#" class="nav-link text-secondary">Login</a></li>
</ul>

サイドメニューとメインコンテンツを囲む要素の設定

サイドメニューとメインコンテンツをdiv要素で囲み、クラスに以下3つのクラスを指定します。

  • d-flex
  • flex-row
  • w-100

flex-rowクラスをflexコンテナに指定することで、子要素であるflexアイテムを左から右に配置します。

flex-direction: row !important;

またサイドメニューとメインコンテンツの高さは、ヘッダーの高さを引いた高さに設定します。calc()関数を利用して以下スタイルを適用させます。

height: calc(100% - 50px)

ページ全体のコードは以下のようになります。

<html class="h-100">
    <body class="h-100">
        <header class="w-100 d-flex justify-content-between align-items-center bg-light px-3">
            <!— ヘッダーの内容 -->
        </header>
        <div class="d-flex flex-row w-100" style="height: calc(100% - 50px)">
            <!— サイドメニュー -->
            <!— メインコンテンツ -->
        </div>
    </body>
</html>

サイドメニューの設定

サイドメニュー:nav要素

サイドバーをメニューとして使用しますので、ここではnav要素を使用します。nav要素は次のように記入します。

<!— サイドメニュー -->
<nav class ="bg-dark">
   <!— メニュー内容 -->
</nav>

nav要素に追加したbg-darkクラスは背景色を黒色に設定します。

サイドメニューの横幅はここでは230pxで固定します。cssファイルに以下を追加してください。

nav {
width: 230px;
}

メニューの設定

サイドメニューの各メニューは以下のように記入します。

<nav class="bg-dark">
    <ul class="nav flex-column m-0 p-3">
        <li class="nav-item mb-2"><a href="#" class="nav-link">Python</a></li>
        <li class="nav-item mb-2"><a href="#" class="nav-link">Django</a></li>
    </ul>
</nav>

メニューの色と背景色をcssで変更します。

.nav-link {
    color: white;
    background-color: rgba(255, 255, 255, 0.493);
}

メインコンテンツの設定

メインコンテンツの部分はmain要素で囲み、w-100クラスとbg-lightクラスを指定します。

<!— メインコンテンツ -->
<main class="w-100 bg-light" >
<!— タイトルバー -->
<!— コンテンツ -->
</main>

main要素の内部にタイトルバーとコンテンツを入れ込みます。

タイトルバー

タイトルバーは以下のように記述します。

<!— タイトルバー -->
<div class="bg-light border shadow-sm d-flex flex-row align-items-center">
    <div class="navbar-brand toggle-menu">
        <button class="btn btn-light btn-sm" id="toggle"><i class="fas fa-bars fa-lg"></i></button>
    </div>
    <div class="fs-4 fw-bold">Dashboard</div>
</div>

コンテンツ

メインのコンテンツ部分は以下のように記述します。

<!— コンテンツ -->
<div class="p-3">
    <div class="d-flex flex-row">
        <div class="card mx-1" style="max-width: 15rem;">
            <img src="https://office54.net/static/image/252/outlook-receive.png" alt="img" class="card-img-top">
            <div class="card-body">
                <h4 class="card-title">カードの見出し</h4>
                <p class="card-text">カードの内容</p>
                <a href="#" class="btn btn-primary stretched-link">ボタン</a>
            </div>
        </div>
        <div class="card mx-1" style="max-width: 15rem;">
            <img src="https://office54.net/static/image/224/excel_windows.png" alt="img" class="card-img-top">
            <div class="card-body">
                <h4 class="card-title">カードの見出し</h4>
                <p class="card-text">カードの内容</p>
                <a href="#" class="btn btn-primary stretched-link">ボタン</a>
            </div>
        </div>
    </div>
</div>

ここではコンテンツにカード(card)を入れ込んでいます。

サイドメニューを表示・非表示にするJS

ボタンをクリック時にサイドメニューを表示・非表示にするため以下JavaScriptコードを追加します。

<script type="text/javascript">
    window.onload = () => {
        // toggleボタン
        let sidemenuToggle = document.getElementById('toggle')
        // メインコンテンツを囲むmain要素
        let page = document.getElementsByTagName('main')[0];
        // 表示状態 trueで表示中 falseで非表示
        let sidemenuStatus = true;
        // ボタンクリック時のイベント
        sidemenuToggle.addEventListener('click', () => {
            // 表示状態を判定
            if(sidemenuStatus){
                page.style.cssText = 'margin-left: -230px'
                sidemenuStatus = false;
            }else{
                page.style.cssText = 'margin-left: 0px'
                sidemenuStatus = true;
            }
        })
    }
</script>

このJavaScriptの動きとしては、ボタンが押下されたらmain要素を左に移動させてサイドメニューを非表示にするというものです。

もう一度ボタンを押すと、main要素を元の位置に戻します。

またCSSアニメーションで表示・非表示に動きをつけます。

main {
    transition: 0.3s all ease;
}

これでサイドメニューを表示・非表示できるWebアプリケーション用テンプレートが完成します。

テンプレートの全コード

本記事で解説したテンプレートの全コードを以下に記します。

<html class="h-100">
    <head>
        <title>OFFICE54</title>
        <style media="screen">
            header{
                height: 50px;
                box-shadow: 0px 0px 5px 0px hsla(0, 0%, 7%, 0.3);
            }
            nav {
                width: 230px;
            }
            .nav-link {
                color: white;
                background-color: rgba(255, 255, 255, 0.493);
            }
            main {
                transition: 0.3s all ease;
            }
        </style>
    </head>
    <body class="h-100">
        <header class="w-100 d-flex justify-content-between align-items-center bg-light px-3">
            <!— ヘッダーの内容 -->
            <h1 class="mx-2 fs-4 text-primary fw-bold">OFFICE54</h1>
            <ul class="navbar-nav d-flex flex-row">
                <li class="nav-item mx-3 text-muted active"><a href="#" class="nav-link text-secondary">New</a></li>
                <li class="nav-item mx-3 text-muted"><a href="#" class="nav-link text-secondary">Login</a></li>
            </ul>
        </header>
        <div class="d-flex flex-row w-100" style="height: calc(100% - 50px)">
            <!— サイドメニュー -->
            <nav class="bg-dark">
                <ul class="nav flex-column m-0 p-3">
                    <li class="nav-item mb-2"><a href="#" class="nav-link">Python</a></li>
                    <li class="nav-item mb-2"><a href="#" class="nav-link">Django</a></li>
                </ul>
            </nav>
            <!— メインコンテンツ -->
            <main class="w-100 bg-light">
                <!— タイトルバー -->
                <div class="border shadow-sm d-flex flex-row align-items-center bg-light">
                    <div class="navbar-brand toggle-menu">
                        <button class="btn btn-light btn-sm" id="toggle"><i class="fas fa-bars fa-lg"></i></button>
                    </div>
                    <div class="fs-4 fw-bold">Dashboard</div>
                </div>
                <!— コンテンツ -->
                <div class="p-3">
                    <div class="d-flex flex-row">
                        <div class="card mx-1" style="max-width: 15rem;">
                            <img src="https://office54.net/static/image/252/outlook-receive.png" alt="img" class="card-img-top">
                            <div class="card-body">
                                <h4 class="card-title">カードの見出し</h4>
                                <p class="card-text">カードの内容</p>
                                <a href="#" class="btn btn-primary stretched-link">ボタン</a>
                            </div>
                        </div>
                        <div class="card mx-1" style="max-width: 15rem;">
                            <img src="https://office54.net/static/image/224/excel_windows.png" alt="img" class="card-img-top">
                            <div class="card-body">
                                <h4 class="card-title">カードの見出し</h4>
                                <p class="card-text">カードの内容</p>
                                <a href="#" class="btn btn-primary stretched-link">ボタン</a>
                            </div>
                        </div>
                    </div>
                </div>
            </main>
        </div>
    </body>
    <script type="text/javascript">
        window.onload = () => {
            // toggleボタン
            let sidemenuToggle = document.getElementById('toggle')
            // メインコンテンツを囲むmain要素
            let page = document.getElementsByTagName('main')[0];
            // 表示状態 trueで表示中 falseで非表示
            let sidemenuStatus = true;
            // ボタンクリック時のイベント
            sidemenuToggle.addEventListener('click', () => {
                // 表示状態を判定
                if(sidemenuStatus){
                    page.style.cssText = 'margin-left: -230px'
                    sidemenuStatus = false;
                }else{
                    page.style.cssText = 'margin-left: 0px'
                    sidemenuStatus = true;
                }
            })
        }
    </script>
</html>