画面全体に表示するメニューを作る(HTML/CSS/JS)

前書き

画面全体に表示するメニューの作り方を掲載しています。

目次

  1. 見本
  2. HTML
  3. CSS
  4. jQuery
  5. 参考

見本

当ページに実装しています。ページの右上にあるボタンをクリックして下さい。

仕様

  • はみ出た分はスクロールして見れる
  • 後ろのコンテンツはスクロールしない
  • 表示前後で、見た目上の位置は変わらない
  • 表示する時にガタつかない

HTML


<!-- 全画面表示のメニュー -->
<div class="fs hidden" data-fs-wrap>
  <div class="fs-wrap">
    <div class="fs-inner">

      <!-- fs-block 一つ目 -->
      <div class="fs-block">
        <div class="fs-parent" data-fs-parent>見出し1</div>
        <ul class="fs-child-ul" data-fs-child>
          <li class="fs-child-li">メニューメニュー</li>
          <li class="fs-child-li">メニュー</li>
          <li class="fs-child-li">メニュー</li>
          <li class="fs-child-li">メニュー</li>
        </ul>
      </div>

      <!-- fs-block 二つ目 -->
      <!-- 中略 -->

    </div>
  </div>
</div>

<!-- メニュー表示ボタン -->
<div class="mn" data-mn-wrap>
  <div class="mn-in">
    <div class="mn-bar mn-bar01"></div>
    <div class="mn-bar mn-bar02"></div>
    <div class="mn-bar mn-bar03"></div>
  </div>
  <p class="mn-text"></p>
</div>

CSS

工夫したこと

  1. bodyのY軸にスクロールバーを出す
  2. .fsのY軸にスクロールバーを出す
  3. .fsの横幅を100vwにして、bodyのスクロールバーの下に入れ込む

全画面表示に関連するSCSS


html{
//  当サイト用の設定
//  height: 100%;
//  @media screen and (min-width: 768px) {
//    min-width: 〇〇
//  }
}
body{
  overflow-y: scroll;
  //メニューが表示している時は、bodyにfixedを指定する。
  &.js-fixed{
    position: fixed; width: 100%; height: 100%;
  }
}
.hidden{
  //非表示1
  display: none;
}
.fs{
  //fixedにする
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  //スクロールバーを、bodyのスクロールバーの下に入れ込む
  overflow-y: scroll; min-width: 100vw;
  //色
  color: #fff; background: rgba(#000,0.9);
  //非表示2
  opacity: 0; z-index: -10; transition: 0.2s;
  //表示
  &.active{
    opacity: 1; z-index:1001;
  }
}
.fs-wrap{
  @media screen and (min-width: 768px) {
    //上下左右中央に寄せる
    display: flex; align-items: center; min-height: 100%;
  }
}

リストに関連するSCSS



.fs-inner{
  padding: 70px 20px 20px;
  @media screen and (min-width: 768px) {
    display: flex; flex-wrap: wrap; justify-content: center; width: 100%; padding: 20px 20px;
  }
}
.fs-block{
  margin: 20px 0 0;
  &:nth-of-type(1){
    margin-top: 0;
  }
  @media screen and (min-width: 768px) {
    width: 50%; max-width: 400px; padding: 20px 20px; margin: 0;
  }
}
.fs-parent{
  position: relative; padding: 0 2em 0 0; cursor: pointer;
  &::after{
    content: "+"; position: absolute; top: 0; right: 0;
  }
  &.active{
    &::after{
      content: "-";
    }
  }
  @media screen and (min-width: 768px) {
    cursor: auto;
    &::after{
      display: none;
    }
  }
}
.fs-child-ul{
  display: none;
  @media screen and (min-width: 768px) {
    display: block;
  }
}
.fs-child-li{
  padding: 0.5em 0;
  &:nth-of-type(1){
    border-top: 1px solid #aaa; margin: 10px 0 0;
  }
}

ボタンに関連するSCSS


.mn{
  position: fixed; top: 0;right: 0; z-index: 1002; width: 60px; height: 60px;
  color: #fff; background: #845080; padding: 13px 0 0; cursor: pointer;
  @media screen and (min-width: 768px) {
    width: 80px; height: 80px; padding: 23px 0 0;
  }
}
.mn-in{
  position: relative; width: 30px; height: 15px; margin: auto;
}
.mn-bar{
  position: absolute; width: 100%; height: 1px; background: #fff; transition: .2s;
}
.mn-bar01{
  top: 0;
}
.mn-bar02{
  top: 7px;
}
.mn-bar03{
  bottom: 0;
}
.mn-text{
  font-size: 10px; line-height: 1; text-align: center; margin: 10px 0 0;
  &::before{
    content: "MENU";
  }
}
// アクティブ
.mn.active{
  .mn-bar01{
    transform: translateY(7px) rotate(-45deg);
  }
  .mn-bar02{
    opacity: 0;
  }
  .mn-bar03{
    transform: translateY(-7px) rotate(45deg);
  }
  .mn-text{
    &::before{
      content: "CLOSE";
    }
  }
}

jQuery

工夫したこと

  1. bodyの位置をずらすことで、見た目上は、コンテンツの位置を変えない

const btn = $('[data-mn-wrap]');
const fullscreen = $('[data-fs-wrap]');
let isActive = false;
let wTop = 0;
let wLeft = 0;

//初め
fullscreen.removeClass("hidden");

//メニューボタン クリック
btn.on("click",function(){
  if( isActive ){
    menuClose();
  }else{
    menuOpen();
  }
});

//全画面表示
function menuOpen(){
  btn.addClass("active");
  fullscreen.addClass("active");
  //bodyの位置をずらすことで、見た目上は、コンテンツの位置を変えない
  wTop = $(window).scrollTop();
  wLeft = $(window).scrollLeft();
  $("body").css({'top': -(wTop), 'left' : -(wLeft)}).addClass("js-fixed");
  isActive = true;
}

//非表示
function menuClose(){
  btn.removeClass("active");
  fullscreen.removeClass("active");
  //fixedを解除して、元の位置に戻す。
  $("body").removeClass("js-fixed").css({'top': '', 'left' : ''});
  $("html, body").animate({scrollTop: wTop},0);
  isActive = false;
}

// スマホの時だけサブメニューを開閉させる
$("[data-fs-parent]").on("click",function(){
  const ww = window.innerWidth;
  const parent = $(this);
  const child = $(this).next();

  if(ww < 768){
    if( parent.hasClass("active")){
      parent.removeClass("active");
      child.slideUp(200,function(){
        //スライドアップしたら、style属性のdisplay:noneを消す
        child.css({'display':''});
      });
    }else{
      parent.addClass("active");
      child.slideDown(200);
    }
  }
});

参考

レスポンシブデザインでスマホだけアコーディオン

jquery ハンバーガーメニューを作ってみよう(基本〜応用の入り口まで)

関連記事

開閉するボックスを作る(HTML/CSS/JS)

CSSを使って自動で番号を振る

WEBページの部品作り

先頭に戻る
ページの先頭に戻る