menu flexible layout

by liveasnotes

HTML

<input type="checkbox" id="menu_tgl">
<label for="menu_tgl" data-ui>menu</label>
<header>
  <nav>
    <ul id="menu_list">
      <li><a href="#">AAA</a></li>
      <li><a href="#">BBB</a></li>
      <li><a href="#">CCC</a></li>
    </ul>
  </nav>
</header>

CSS

*,*::before,*::after {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

[data-ui] {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

#menu_tgl,
[for="menu_tgl"] {/* toggle */
  position: fixed;
  top: 0;
  right: 0;
  z-index: 0; /* @SP, for make UNtouchable */
  display: none;
  width: 50px;
  height: 50px;
  background: palegreen;
  opacity: 0.5;
}

#menu_list {
  display: flex;
  list-style: none;
  text-align: center;
  background: palegreen;
  transition: 0s;
}

#menu_list > li {
  border: 1px solid gray;
  padding: 1em;
  margin: 1em;
}

/* at transition PC -> SP, to prevent show animation of menu, wrapper of menu need to change own position with no transition time */
nav {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
}

nav a {
  display: block;
}

/* @SP */
@media screen and (max-width: 768px) {
  #menu_tgl,
  [for="menu_tgl"] {
    display: block;
    z-index: 100; /* @SP, for make touchable */
  }

  nav {
    top: auto;
    bottom: 100%;
  }

  #menu_list {
    flex-direction: column;
    opacity: 0;
    transition: 0.5s;
  }

  #menu_tgl:checked ~ header #menu_list {
    transform: translateY(100%);
    opacity: 1;
  }
}

JavaScript

// cf. .matchMedia()でJSでもメディアクエリを使って条件分岐する | SPYWEB
// https://spyweb.media/2018/01/10/css-media-queries-in-js-matchmedia/

// cssはPCファーストで書いてたけど,
// jsはSPファーストで書いてるので,「MAX-width: 768px」ではなく,「MIN-width: 768.0001px」
const mediaQuery = matchMedia('(min-width: 768.0001px)');

function handle(mq) {
  if (mq.matches) {
    document.getElementById("menu_tgl").checked = false;
  }
}

// ページが読み込まれた時に実行
handle(mediaQuery);

// ウィンドウサイズが変更されても実行されるように
mediaQuery.addListener(handle);