yoshiislandblog.net
元営業の駆け出しアラサーSEが、休日にMACと戯れた際の殴り書きメモ。日々勉強。日々進歩。
20220508_wordpress_sp-menu_hamburger_5

仕組みを理解しながら、SPメニュー(バンバーガーメニュー)をHTML・CSS・Javascriptで作成する

2022-05-08

やりたいこと

PCの場合は、サイドバーにウィジェットを表示していたが、SP(スマートフォン)の場合は、サイドバーが邪魔になるので非表示にした
参考:WordPressレスポンシブデザインでのサイドバーの作り方(SPではサイドバーを非表示とする)
その代わりに、SPでは、ボタンを押すと、サイドメニューが表示されるようにしたい

実装方針:ハンバーガーメニュー

まずは、左上にハンバーガーアイコンを設置する
このアイコンは、「position: fixed;」を使って、スクロールしても、同じ位置に固定されるようにする

20220508_wordpress_sp

三本の線は、細い長方形。CSSで作成する

20220508_wordpress_sp-menu_hamburger_3

このアイコンはクリックすると、バツ印になる
クリックすると、真ん中の線が消え、残りの線が回転することによってバツ印となる

20220508_wordpress_sp-menu_hamburger_2
20220508_wordpress_sp-menu_hamburger_4

実装方針:SPメニュー表示・非表示

20220508_wordpress_sp-menu_hamburger_5

SPメニューは、デフォルトは画面の外に隠れていて、ハンバーガーアイコンをクリックすると表示される

20220508_wordpress_sp-menu_hamburger_6

CSSで、「spmenu-open」というクラスが無い時は、隠れた状態のポジション、「spmenu-open」というクラスありでは、表示された状態のポジションを定義しておく

JavaScriptでハンバーガーアイコンをクリックしたら、「spmenu-open」というクラスを付与するようにすれば、クリックに連動して、表示非表示が切り替えられる

SP用サイドバーの作成

やりたいことと、実装方針が決まったので、実際に実装していく

以下記事を参考に、SP用サイドバーを作成しておく
(idが被るため、PC用に呼び出しているサイドバーを呼び出すことはできない)
参考:WordPressでオリジナルテンプレートを作る時にSidebarにWidgetsを追加できるようにする(サイドバーの有効化)

HTMLの作成

長くなるので、SP用メニュー部分は別ファイル(spmenu.php)に外出しして、呼び出すようにする

$ cat spmenu.php
<div id="spmenu-wrapper">

  <!-- ハンバーガーアイコン -->
  <div id="hamburger">
    <span class="hamburger-line" id="hamburger-line-1"></span>
    <span class="hamburger-line" id="hamburger-line-2"></span>
    <span class="hamburger-line" id="hamburger-line-3"></span>
  </div>

  <!-- SP用メニュー -->
  <div id="sp-menu">
    <div id="sp-menu-widget-area">
      <?php dynamic_sidebar( 'Sidebar-SP' ); ?>
    </div>
  </div>
</div>

<script>
  window.onload = function () {
    var wrapper = document.getElementById('spmenu-wrapper');
    var hamburger = document.getElementById('hamburger');
    hamburger.addEventListener('click', function () {
      wrapper.classList.toggle('spmenu-open'); // クリックされたら'spmenu-open'クラスを付与
    });
  };
</script>
$ cat index.php
<!DOCTYPE html>
<html <?php language_attributes( ); ?>> <!-- multi-language supports -->
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="<?php bloginfo( 'charset' ); ?>">
    <link rel="stylesheet" href="<?php echo get_stylesheet_uri( ); ?>">
    <?php wp_head(); ?>
  </head>

  <body <?php body_class( ); ?>>

    <?php get_template_part('spmenu'); ?> <!-- SP用メニューの呼び出し -->

    <div id="wrapper">
      <aside>
        <?php dynamic_sidebar( 'Sidebar' ); ?>
      </aside>
      <div id="contents">
        contentsだよ
      </div>
    </div>

    <?php wp_footer(); ?>
  </body>
</html>

CSSの作成

CSSは以下の通り

/* spmenu
   ========================================================================== */
@media screen and (min-width:751px) {
  #spmenu-wrapper {
    display: none;
  }
}

@media screen and (max-width:750px) {
  #hamburger {
    position: fixed;
    left: 10px;
    top: 10px;
    z-index: 102; /* sp-menuより前 */
    height: 50px;
    width: 50px;
    border-radius: 50%;
    background: #ffffff;
    opacity: 0.8;
  }

  .hamburger-line {
    position: absolute;
    height: 2px;
    left: 10px;
    width: 30px;
    background: #616161;
    transition: 0.5s; /* transformで動かす時のスピード */
  }

  #hamburger-line-1 {
    top: 12px;
  }
  #hamburger-line-2 {
    top: 24px;
  }
  #hamburger-line-3 {
    top: 36px;
  }

  .spmenu-open #hamburger-line-1 {
    transform: rotate(-45deg); /* クリックされたら回転 */
    top: 24px;
  }
  .spmenu-open #hamburger-line-2 {
    opacity: 0; /* クリックされたら真ん中の線は見えないようにする */
  }
  .spmenu-open #hamburger-line-3 {
    transform: rotate(45deg); /* クリックされたら回転 */
    top: 24px;
  }

  #sp-menu {
    position: fixed;
    left: -250px; /* クリックされる前は画面の外左側に隠す */
    top: 0;
    width: 250px;
    height: 100vh; /* 画面いっぱい */
    z-index: 101; /* hamburgerより後ろ */
    overflow-y: auto; /* メニューが多くなったらスクロールできるように */
    transition: 0.5s; /* transformで動かす時のスピード */
    background: #ffffff;
    opacity: 0.9;
  }
  .spmenu-open #sp-menu {
    transform: translateX(250px)  /* クリックされたら画面の中へ */
  }

  #sp-menu-widget-area {
    margin-top: 60px; /* ハンバーガーに被らないように下げる */
    padding: 10px;
  }
}

これで完成。問題なく動作するはず