8192.jp

右から現れるシンプルなハンバーガーメニュー

2023/09/03 2023/09/03

よくあるハンバーガーメニューを実装するためのコードです。

目次

    仕様

    • メニューボタンをクリックすると画面右からメニューが現れ、背景が暗くなる
    • メニュー展開時はメニューボタンが✕に変化する
    • 背景をクリックしたらメニューを閉じる
    • 各動作は全てアニメーションさせる

    HTML

    <div class="menu_btn open">
    	<i></i>
    	<i></i>
    	<i></i>
    	<i></i>
    </div>
    
    <div class="menu_wrap">
    	<div class="menu_content">
    		<ul>
    			<li>メニュー - 1</li>
    			<li>メニュー - 2</li>
    			<li>メニュー - 3</li>
    		</ul>
    	</div>
    </div>
    .menu_btnメニューボタン
    .menu_wrapCSSでページ全体を覆い、メニュー展開時に背景を暗くするために使用します
    .menu_contentメニュー本体

    CSS

    .menu_btn{
    	position: fixed;
    	top: 10px;
    	right: 12px;
    	z-index: 9999;
    	width: 40px;
    	height: 40px;
    	cursor: pointer;
    }
    .menu_btn i{
    	display: block;
    	position: absolute;
    	left: 0;
    	width: 40px;
    	height: 4px;
    	background: #000;
    	opacity: 1;
    	transition: 0.3s;
    }
    .menu_btn i:nth-child(1){
    	top: 5px;
    }
    .menu_btn i:nth-child(2),.menu_btn i:nth-child(3){
    	top: 50%;
    	transform: translateY(-50%);
    }
    .menu_btn i:nth-child(4){
    	bottom: 5px;
    }
    .menu_btn.close i:nth-child(1),.menu_btn.close i:nth-child(4){
    	opacity: 0;
    }
    .menu_btn.close i:nth-child(2){
    	transform: rotate(45deg);
    }
    .menu_btn.close i:nth-child(3){
    	transform: rotate(-45deg);
    }
    
    .menu_wrap{
    	visibility: hidden;
    	position: fixed;
    	top: 0;
    	left: 0;
    	width: 100%;
    	height: 100vh;
    	background: rgba(0,0,0,0.5);
    	opacity: 0;
    	transition: 0.3s;
    }
    .menu_wrap.open{
    	visibility: visible;
    	opacity: 1;
    }
    .menu_wrap .menu_content{
    	display: flex;
    	flex-direction: column;
    	position: fixed;
    	top: 0;
    	right: 0;
    	transform: translateX(100%);
    	box-sizing: border-box;
    	width: 60vw;
    	max-width: 640px;
    	height: 100vh;
    	padding: 60px 20px 20px;
    	background: #fff;
    	box-shadow: 0 0 16px rgba(0,0,0,0.5);
    	transition: 0.5s;
    }
    .menu_wrap.open .menu_content{
    	transform: translateX(0);
    }

    ボタンの色やサイズ、デザインはサイトに合わせて適宜変更してください。

    また、メニューのサイズはページ全体の60vwかつ、PCで大きくなりすぎないように最大値を640pxに制限しています。

    JavaScript

    document.addEventListener("DOMContentLoaded", function() {
        var menuBtns = document.querySelectorAll(".menu_btn");
        var menuWrap = document.querySelector(".menu_wrap");
        var menuContents = document.querySelectorAll(".menu_content, .menu_btn");
    
        for (var i = 0; i < menuBtns.length; i++) {
            menuBtns[i].addEventListener("click", function() {
                menuWrap.classList.toggle("open");
                this.classList.toggle("open");
                this.classList.toggle("close");
            });
        }
    
        menuWrap.addEventListener("click", function() {
            menuWrap.classList.remove("open");
            for (var i = 0; i < menuBtns.length; i++) {
                menuBtns[i].classList.remove("close");
                menuBtns[i].classList.add("open");
            }
        });
    
        for (var i = 0; i < menuContents.length; i++) {
            menuContents[i].addEventListener("click", function(e) {
                e.stopPropagation();
            });
        }
    });

    メニューボタンやメニュー本体の制御を行っています。

    jQuery版

    jQueryを使用する場合はこちらです。

    $(document).ready(function() {
    	$(".menu_btn").click(function() {
    		$(".menu_wrap").toggleClass("open");
    		$(this).toggleClass("open close");
    	});
    	$(".menu_wrap").click(function() {
    		$(".menu_wrap").removeClass("open");
    		$(".menu_btn").addClass("open").removeClass("close");
    	});
    	$('.menu_content,.menu_btn').on('click', function(e) {
    		e.stopPropagation();
    	});
    });

    実際の動作

    See the Pen Untitled by Leo_8192 (@Leo_8192) on CodePen.

    メニューボタンをクリックして動作を確認してみてください。

    背景のロック機能

    もしメニュー展開時に背景のスクロールをロックしたい場合、スクリプトを下記のように変更してください。

    JavaScript

    document.addEventListener("DOMContentLoaded", function() {
        var menuBtns = document.querySelectorAll(".menu_btn");
        var menuWrap = document.querySelector(".menu_wrap");
        var body = document.body;
        var menuContents = document.querySelectorAll(".menu_content, .menu_btn");
    
        for (var i = 0; i < menuBtns.length; i++) {
            menuBtns[i].addEventListener("click", function() {
                menuWrap.classList.toggle("open");
                this.classList.toggle("open");
                this.classList.toggle("close");
    
                if (menuWrap.classList.contains("open")) {
                    body.style.overflow = "hidden";
                } else {
                    body.style.overflow = "auto";
                }
            });
        }
    
        menuWrap.addEventListener("click", function() {
            menuWrap.classList.remove("open");
            for (var i = 0; i < menuBtns.length; i++) {
                menuBtns[i].classList.remove("close");
                menuBtns[i].classList.add("open");
            }
            body.style.overflow = "auto";
        });
    
        for (var i = 0; i < menuContents.length; i++) {
            menuContents[i].addEventListener("click", function(e) {
                e.stopPropagation();
            });
        }
    });

    jQuery

    $(document).ready(function() {
    	$(".menu_btn").click(function() {
    		$(".menu_wrap").toggleClass("open");
    		$(this).toggleClass("open close");
    		if ($(".menu_wrap").hasClass("open")) {
    				$("body").css("overflow", "hidden");
    		} else {
    				$("body").css("overflow", "auto");
    		}
    	});
    	$(".menu_wrap").click(function() {
    		$(".menu_wrap").removeClass("open");
    		$(".menu_btn").addClass("open").removeClass("close");
    		$("body").css("overflow", "auto");
    	});
    	$('.menu_content,.menu_btn').on('click', function(e) {
    		e.stopPropagation();
    	});
    });