みかづきブログ・カスタム

基本的にはちょちょいのほいです。

JavaScriptを1行も書くことなくドロワーメニューをつくる 💻

f:id:kimizuka:20201023181845g:plain

HTMLのcheckボックス、CSSの隣接セレクタ、target擬似クラスを使って、JavaScriptを書かずにドロワーメニューをつくってみました。

ざっくりとだけ解説すると、

  • メニューボタンに見える要素が実はinput要素(チェックボックス)
  • inputにチェックの有無でメニューの開閉の状態を管理
  • メニューの開閉は隣接セレクタを使い、チェックが入っている要素の隣の要素を制御
  • メニューがそれぞれリンクになっていて、クリック時にハッシュを付与
  • ハッシュがついた際に、target擬似クラスを使いコンテンツの表示・非表示を切り替え

という流れになっています。


DEMO


See the Pen
Drawer Menu made from CSS only
by kimmy (@kimmy)
on CodePen.




ソースコード

HTML

<input class="btn" id="btnMenu" type="checkbox"/>
<nav id="menu">
  <a class="btn" href="#a">MENU_A</a>
  <a class="btn" href="#a">MENU_A</a>
  <a class="btn" href="#b">MENU_B</a>
  <a class="btn" href="#c">MENU_C</a>
  <a class="btn" href="#d">MENU_D</a>
</nav>
<div class="result" id="a">A</div>
<div class="result" id="b">B</div>
<div class="result" id="c">C</div>
<div class="result" id="d">D</div>

SCSS

* {
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  -webkit-touch-callout: none;
  -webkit-user-select: none;
}

html {
  height: 100%;
  color: #212121;
  font: 10px AvenirNext-Heavy;
}

body {
  height: 100%;
  background: #f8f8f2;
}

[href] {
  color: #212121;
  text-decoration: none;
}

.btn {
  cursor: pointer;
}

.result {
  visibilty: hidden;
  position: fixed;
  top: 50%; left: 50%;
  margin: -100px;
  width: 200px; height: 200px;
  font-size: 20rem;
  line-height: 200px;
  text-align: center;
  opacity: 0;
}

#btnMenu {
  $lineMargin: 20px;
  $lineWidth: 28px;
  $lineHeight: 4px;
  $btnSize: $lineWidth + $lineMargin * 2;
  $color: #bdbdbd;

  display: block;
  position: fixed;
  margin: 0;
  border: 0;
  width: $btnSize; height: $btnSize;
  top: 0px; left: 0px;
  z-index: 5;
  transition: background .2s ease-in-out, width 0s .2s ease-in-out, height 0s .2s ease-in-out;
  -webkit-appearance: none;

  &:focus {
    outline: none;
  }
  
  &:before {
    position: absolute;
    top: $btnSize / 2 - $lineHeight / 2; left: $lineMargin;
    width: $lineWidth; height: $lineHeight;
    background: $color;
    content: "";
    box-shadow: 0 -8px 0 $color, 0 8px 0 $color;
  }

  &:checked {
    width: 100%; height: 100%;
    background: rgba(0, 0, 0, .2);
    transition: background .2s ease-in-out;
  }
}

#menu {
  $width: 200px;

  position: fixed;
  top: 0; bottom: 0;
  left: -$width - 10;
  width: $width;
  background: #fff;
  overflow: hidden;
  z-index: 10;
  box-shadow: 0 0 2px rgba(0, 0, 0, .4);
  transition: left ease-in-out .2s;

  .btn {
    box-sizing: border-box;
    display: block;
    padding-left: 20px;
    width: $width - 10; height: 44px;
    font-size: 1.4rem;
    line-height: 44px;
    -webkit-tap-highlight-color: rgba(0, 0, 0, .2);
  }

  &:before {
    box-sizing: border-box;
    display: block;
    margin-bottom: 10px;
    padding-left: 20px;
    border-bottom: solid 1px #bdbdbd;
    width: 100%; height: 60px;
    color: #bdbdbd;
    font-size: 2rem;
    content: "MENU";
    line-height: 60px;
  }

  &:after {
    box-sizing: border-box;
    display: block;
    position: absolute;
    bottom: 0; left: 0;
    padding-left: 20px;
    border-top: solid 1px #bdbdbd;
    width: 100%; height: 40px;
    color: #bdbdbd;
    font-size: 1rem;
    content: "© KIMIZUKA";
    line-height: 40px;
  }
  
  #btnMenu:checked + & {
    left: 0;
  }
}

.result:target {
  visibilty: visible;
  opacity: 1;
}