M's Web Design produced by k.toma

【スマホ対応】ハンバーガーメニューを開いた時に背景をスクロールさせない方法

  coding

スマホでよく見るハンバーガーメニュー。
メニューが長いと開いた時に画面下が見切れて、スクロールが必要になってくる。

でも、メニューをスクロールしようとすると背景もスクロールされてしまうことありませんか?

スクロールバーが2重に見えたり、
スマホだと上手くメニューをスクロール(スワップ)できなかったり。。めっちゃイラ(`´)

 

 

 

こちら、cssとjavascriptで解決します!

 

結論

メニューが開いてる時だけ背景を固定することで、メニューのみをスクロールすることができます。

結果のプレビューはこちら↓ または別ウインドウで確認できます。(ダウンロード可)

 

プレビュー

 

 

そしてソースはコチラ↓

 

とその前に、
長いので先にポイントを説明すると

  • メニューの開閉は、js不要でcssのみで実装。2行目にあるチェックボックスを使います。
  • 「メニューが開いてる時は背景を固定する」の設定が、209行目からのjavascript。
    チェックボックスにチェックがあるかどうかの判定から、bodyタグにスタイルのoverflowを使ってhidden/autoをあてることで、背景の固定/解除を切り替えてます。
  • 149行目では、メニューが開いた時はそのメニュー外枠の高さを明示すること!
    でないと思ったようにスクロールできない場合があります。画面いっぱいにメニューを開きたい場合はheight: 100vhで良いと思います。
<body>
 <input type="checkbox" id="menuBtnCheck" />
 <div class="wrapper">

   <header class="g-header">

     <div class="g-header-inner">

      <div class="header-logo-wrap">
       <h1 class="header-logo">ハンバーガーメニュー</h1>
      </div> <!-- .header-logo-wrap -->

      <div type="button" id="navBtn">
       <label for="menuBtnCheck" id="menuBar" class="btn-open">
        <span></span>
        <span></span>
        <span></span>
       </label>
      </div> <!-- #navBtn -->

      <div id="navigation" class="overlay">
       <nav>
        <ul>
         <li>メニュー1</li>
         <li>メニュー2</li>
         <li>メニュー3</li>
         <li>メニュー4</li>
         <li>メニュー5</li>
        </ul>
       </nav>
       <div class="menu_bk-1">
        <p>ナビメニューの下部要素1</p>
       </div>
       <div class="menu_bk-2">
        <p>ナビメニューの下部要素2</p>
       </div>
      </div><!-- #navigation -->

    </div><!-- .g-header-inner -->

   </header>
   <main>
    <p>メインコンテンツ</p>
   </main>

  </div><!-- .wrapper -->

  <footer>
   <p>フッター</p>
  </footer>
</body>

<style>
/* ヘッダー */
.header-logo {
 font-size: 1.5em;
}
.g-header {
 position: fixed;
 top: 0;
 left: 50%;
 transform: translateX(-50%);
 width: calc(100% - 35px);
 z-index: 99;
 padding: 0 10px;
 transition: .2s;
}
.header-logo-wrap {
 z-index: 999;
}

/* メニューリンクの装飾 */
nav ul li {
 cursor: pointer;
 transition: .2s;
}
nav ul li:hover {
 opacity: .8;
 background: #eee;
}

/* メニューバー */
#menuBtnCheck {
 display: none;
}
#navBtn {
 position: absolute;
 display: block;
 right: 10px;
 top: 0;
 z-index: 999;
}
#menuBar {
 display: inline-block;
 text-decoration: none;
 position: relative;
 width: 60px;
 height: 60px;
 opacity: 1;
 cursor: pointer;
 z-index: 999;
}
#menuBar > span {
 position: absolute;
 transition-duration: 0.2s;
 background: #534340;
 height: 2px;
}
#menuBar > span {
 left: 16px;
 right: 15px;
}
#menuBar > span:nth-child(1) {
 top: 20px;
}
#menuBar > span:nth-child(2) {
 top: 30px;
}
#menuBar > span:nth-child(3) {
 top: 40px;
}

/* メニューが開いた時 */
#menuBtnCheck:checked ~ .wrapper #menuBar > span:nth-child(1) {
 top: 30px;
 position: absolute;
 -ms-transform: rotate(45deg);
 transform: rotate(45deg);
}
#menuBtnCheck:checked ~ .wrapper #menuBar > span:nth-child(2) {
 display: none;
}
#menuBtnCheck:checked ~ .wrapper #menuBar > span:nth-child(3) {
 position: absolute;
 top: 30px;
 -ms-transform: rotate(-45deg);
 transform: rotate(-45deg);
}

/* オーバーレイ */
.overlay {
 display: none;
}
#menuBtnCheck:checked ~ .wrapper .overlay {
 position: fixed;
 top: 68px;
 left: 0;
 right: 0;
 height: 100vh; /* 高さを指定するのがポイント! でないとoverflowが効かない。 */
 z-index: 99;
 display: block;
 overflow: auto;
 box-shadow: 3px 3px 3px #e4e4e4;
 margin: 0;
 padding: 0;
 background: rgba(255,255,255, .75);
}

/* 独自の装飾 */
body {
 color: #534340;
}
header {
 background: #F4FCD9;
}
main {
 height: 90vh;
 background: #C5D8A4;
 box-sizing: border-box;
}
main p {
 text-align: center;
 padding: 45vh 2em 0;
 font-weight: bold;
}
footer {
 text-align: center;
 height: 30vh;
 background: #BB9981;
 box-sizing: border-box;
}
footer p {
 padding: 15vh 2em 0;
 font-weight: bold;
 color: #fff;
}
.menu_bk-1 {
 display: block;
 height: 500px;
 background: #e79f94;
 color: #fff;
 padding: 250px 0 0;
 font-weight: bold;
 text-align: center;
 box-sizing: border-box;
}
.menu_bk-2 {
 display: block;
 height: 500px;
 background: #4e3a3a;
 color: #fff;
 padding: 250px 0 0;
 font-weight: bold;
 text-align: center;
 box-sizing: border-box;
}
</style>

<script>
// bodyへのoverflow設定:ここで背景のスクロールを固定する。
var menuBtnCheck = document.getElementById('menuBtnCheck');
var menuBar = document.getElementById('menuBar');
var body = document.getElementsByTagName('body');

menuBar.onclick = function() { // メニューバーをクリックした時
 if (menuBtnCheck.checked) {
  document.body.style.overflow = 'auto';
 } else {
  document.body.style.overflow = 'hidden';
 }
}
</script>

 


 

以上です!

 

あるサイトの公開後に実機のスマホで確認すると、
ハンバーガーメニューの内容が、画面から見切れててもスクロールができない。2重にスクロールバーが見えて変!という現象が起こりました。

bodyにoverflow:hiddenへの解決にいたるまで時間がかかりとても焦ったので、もし同じ現象に出くわした方はご参考までに。