ニュース・ブログ

ニュース・ブログ一覧UX/UIの記事情報【iOS対応】究極のハンバーガーメニュー(スライドメニュー)

【iOS対応】究極のハンバーガーメニュー(スライドメニュー)

システム開発部のヤマモトです。
スマホサイトでよく実装されている横からスライドするメニュー(ハンバーガーメニュー)の実装についての記事です。
メニューを開いたときにCSSでoverflow:hidden;を指定してもiOS safariでコンテンツ部分がスクロールしてしまう問題を回避しつつスムーズなスライドを実現したスライドメニューの完成形ともいえるメニューです。

仕様

・開閉時メニューの横幅分とコンテンツを外にスクロール
・メニューを開いたときにコンテンツ部分がスクロールしない(iPhoneも)
・開閉ボタンをスクロール追従させる
・できるだけCSSで完結する。

説明

デモ

開閉時の挙動

チェックボックスのオンオフで開閉する仕組みで、開閉部分はCSSのみで動作しています。

<input type="checkbox" id="nav-tgl">
<label for="nav-tgl" class="open nav-tgl-btn"><span></span></label>

 


/*メニュー部分*/
.drower-menu {
transform: translateX(100%);
}
#nav-tgl:checked ~ .drower-menu {
transform: none;
}

/*コンテンツ部分*/
.content-wrapper {
transition: transform .6s cubic-bezier(0.215, 0.61, 0.355, 1);
}
#nav-tgl:checked ~ .content-wrapper {
transform: translateX(-250px);
}
上記labelタグのクリックでチェックボックスのオンオフを検知して
CSSで指定されたメニューとコンテンツのスクロールが実行されます。

メニューを開いた時コンテンツをスクロールさせない


$(function(){
  $('#nav-tgl').on('change', function(){
    var st = $(window).scrollTop();
    if($(this).prop("checked") == true) {
      $('html').addClass('scroll-prevent');
      $('html').css('top', -(st) + 'px');
      $('#nav-tgl').on('change', function(){
        if($(this).prop("checked") !== true) {
          $('html').removeClass('scroll-prevent');
          $(window).scrollTop(st);
        }
      });
    }
  });
});



.scroll-prevent {
position: fixed;
z-index: -1;
width: 100%;
height: 100%;
}

メニューを開いたときhtmlタグのpositionをCSSで絶対位置にし、現在のスクロール位置をjavascriptで指定することでコンテンツの位置を固定しています。
Chrome等のブラウザではhtmlタグに対してoverflow:hidden;を指定することでコンテンツのスクロールを制限することができますがiOS(safari)ではスクロール位置を指定しないと固定することができませんでした。

ソースコード

HTML

<input type="checkbox" id="nav-tgl">
<label for="nav-tgl" class="open nav-tgl-btn"><span></span></label>
<label for="nav-tgl" class="close nav-tgl-btn"></label>
<div class="content-wrapper">
<div class="site-content">
コンテンツ<br>
</div>
</div>
<div class="drower-menu">
<div class="drower-menu-list">
<a href="#">メニュー1</a>
<a href="#">メニュー2</a>
<a href="#">メニュー3</a>
<a href="#">メニュー4</a>
<a href="#">メニュー5</a>
</div>
</div>
CSS


.scroll-prevent {
position: fixed;
z-index: -1;
width: 100%;
height: 100%;
}
#nav-tgl {
display: none;
}
.nav-tgl-btn {
cursor: pointer;
position: fixed;
top: 0;
right: 0;
margin: 0;
}
.open {
z-index: 2;
width: 48px;
height: 48px;
background: #000;
transition: background .6s, transform .6s cubic-bezier(0.215, 0.61, 0.355, 1);
}
.open::before,
.open::after {
content: "";
}
.open span,
.open::before,
.open::after {
content: "";
position: absolute;
top: calc(50% - 1px);
right: 30%;
width: 40%;
border-bottom: 2px solid white;
transition: transform .6s cubic-bezier(0.215, 0.61, 0.355, 1);
}
.open::before {
transform: translateY(-8px);
}
.open::after {
transform: translateY(8px);
}
.close {
z-index: 1;
width: 100%;
height: 100%;
pointer-events: none;
transition: background .6s;
}
#nav-tgl:checked + .open {
background: #dd4884;
transform: translateX(-250px);
}
#nav-tgl:checked + .open span {
transform: scaleX(0);
}
#nav-tgl:checked + .open::before {
transform: rotate(45deg);
}
#nav-tgl:checked + .open::after {
transform: rotate(-45deg);
}
#nav-tgl:checked ~ .close {
pointer-events: auto;
background: rgba(0,0,0,.3);
}
.content-wrapper {
transition: transform .6s cubic-bezier(0.215, 0.61, 0.355, 1);
}
#nav-tgl:checked ~ .content-wrapper {
transform: translateX(-250px);
}
/* メニューデザイン */
.drower-menu {
z-index: 999;
position: fixed;
overflow: auto;
-webkit-overflow-scrolling: touch;
overflow-scrolling: touch;
top: 0;
right: 0;
width: 250px;
height: 100%;
margin: 0;
padding: 0 0 10px;
box-sizing: border-box;
background: #333;
transform: translateX(100%);
transition: transform .6s cubic-bezier(0.215, 0.61, 0.355, 1);
}
.drower-menu a {
display: block;
color: white;
padding: 10px;
text-decoration: inherit;
transition: background .6s;
font-size: 1.4rem;
}
.drower-menu a:hover {
background: black;
}
#nav-tgl:checked ~ .drower-menu {
transform: none;
}
Javascript

$(function(){
  $('#nav-tgl').on('change', function(){
    var st = $(window).scrollTop();
    if($(this).prop("checked") == true) {
      $('html').addClass('scroll-prevent');
      $('html').css('top', -(st) + 'px');
      $('#nav-tgl').on('change', function(){
        if($(this).prop("checked") !== true) {
          $('html').removeClass('scroll-prevent');
          $(window).scrollTop(st);
        }
      });
    }
  });
});

 

 

新たなサービスを展開したいご要望や名古屋のシステム開発会社をお探しでしたら、是非ともお問い合わせください。

週間ブログランキング