みっちぇのWebデザイン研究所

はてなブログのカスタマイズを中心に、ウェブデザインについて研究するブログ

追従するグローバルメニュー【CSSのみ】

グローバルメニューっていうのは、当ブログにあるようなこれ↓

f:id:micche-labo:20211022111544p:plain
グローバルメニュー

とか、これ↓

f:id:micche-labo:20211022112031p:plain:w300
グローバルメニュー2
f:id:micche-labo:20211022112037p:plain:w300
グローバルメニュー3

のようなメニューのこと。

Check!

ハンバーガーメニューの作り方はこちら

micche-labo.hatenablog.com

こんな感じのメニューを画面上部に追従させて、クリックしたら表示、クリックで非表示するようにします。

全部CSSだけで作れます。

ポイントは以下。

  • position:stickyでtopに固定
  • 子要素にもposition:stickyで高さを調節
  • <input type="checkbox">でクリック(タップ)でメニューの中身表示・非表示切り替え、アイコンアニメーション、背景表示
  • チェックボックスと切り替えのためのボタンは<label></label>要素を使い紐づける
  • アイコンは<span></span>で作る
  • 背景は擬似要素で作る
  • 動きはtransitionで作る

手っ取り早く完成形が知りたい方は以下。
JavaScriptはメニューには関係ないです。

See the Pen 追従グローバルナビ by Micche (@micche) on CodePen.

※SCSSで書いてますが、コンパイルすることでCSSで見れます。

f:id:micche-labo:20211022113457p:plain
コンパイル

htmlのマークアップ

 <header>
    <h1>サイトタイトル</h1>
    <div>
      <input type="checkbox" id="toggle">
      <label for="toggle" class="close-btn"><span></span></label>

      <nav id="hidden">
        <ul>
          <li><a href="#sec1">Section1</a></li>
          <li><a href="#sec2">Section2</a></li>
          <li><a href="#sec3">Section3</a></li>
        </ul>
      </nav>

    </div>
  </header>

POINT

  1. header内に、h1divを収納。
  2. h1にはサイトタイトルとヘッダーの背景を設定。
  3. divには、+アイコンと、クリック(タップ)で表示・非表示する要素(今回はグローバルメニュー用のnav要素)を入れる

CSSの設定

最終的に↓の画像のようになります。

f:id:micche-labo:20211023160912p:plain
最終デザイン見本

Menu +を押すことでメニューが表示され、さらにスクロールしても上部に固定されるようにします。

f:id:micche-labo:20211023161233p:plain
最終デザイン見本2

position:sticky;を使用します。

  1. header部分の設定
  2. div要素内の設定

を行います。

参考記事はこちら coliss.com

追従するヘッダー部分

/*ヘッダー部分の設定*/
header {
  height: 0px; /*スクロールしたあとの高さ*/
  position: sticky; /*stickyで上部に固定*/
  top: -100px; /*スクロール前の要素の高さ分引くと画面外に消えてくれる*/
  margin: 0;
  z-index: 9999; /*重ね順を一番上に*/
}
/*ヘッダー内のサイトタイトル部分デザイン*/
header h1 {
  margin: 0;
  background: #75c9e4; /*好きな背景色*/
  color: #ffffff; /*好きな文字色*/
  padding: 0 0.4em; /*左右に余白を少しとる*/
  height: 100px; /*ヘッダーの高さ*/
  line-height: 100px; /*真ん中に寄せるために文字の高さをヘッダー高さと揃える*/
  width: 100vw; /*横幅いっぱい*/
  font-size: 1.7rem; /*文字サイズ*/
}

ここまででヘッダー部分のデザインが完成しました。
次はdiv要素のCSSを設定していきます。

追従するナビ部分その1

Point div要素にposition: relativeを設定します。
これを設定しないと、header要素で設定したtop: -100px;が聞いちゃって、メニューがどっかいっちゃうので、設定しておきます。

f:id:micche-labo:20211023160743p:plain
position指定なしの時

/*メニュー部分*/
header div {
  position: relative;
  margin: 0;
  margin-left: auto;  /*右寄せにする*/
  width: 100vw; /*横幅いっぱい*/
}
@media screen and (min-width: 768px) {
  header div {
    width: 300px; /*PC用の横幅*/
  }
}

PC用の横幅は、横幅いっぱいにしたくなかったので少し幅狭めに設定。
お好みで数値を設定してください。

追従するナビ部分その2

次にnav部分のCSSを設定していきます。

header div nav {
  background: #75c9e4; /*headerで設定した背景色と同じ色*/
  width: 100%; /*div要素内で横幅いっぱい*/
  margin-top: -2em;  /*+アイコン分上げる*/

  border-radius: 0 0 10px 10px; /*左下・右下少し角を丸める*/
  box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 8px 8px rgba(0, 0, 0, 0.05); /*お好みで影つける*/

  /*nav要素クリック前は非表示*/
  visibility: hidden;
  height: 0;
  top: 0;
  right: 0;
  opacity: 0;
  transition: all 0.3s ease;
}

header div nav a {
  color: #ffffff; /*nav内のリンク色*/
  text-decoration: none; /*リンクの下線を消す*/
  display: block; /*ブロック要素にして押しやすいように*/
  padding: .4em; /*押せる範囲を少し拡張するために文字の高さを設定*/
}
/*ホバーで背景色変える*/
header div nav a:hover {
  background: #ffffff80; /*透明度80の白*/
}
/*ul設定*/
header div nav ul {
  margin: 0;
  padding: 2em 1em; /*余白上はアイコン分開ける*/
  list-style: none; /*リストの・を消す*/
}

コメントアウトの通りですが、ほぼデザインについてのCSSです。

Point

header div nav内のmargin-rop:-2em;は、+アイコンのサイズ分上にあげる設定です。
これをしないと不自然に隙間が空くので設定しています。

f:id:micche-labo:20211023160519p:plain
margin-top:-2em;とした時

f:id:micche-labo:20211023160212p:plain
margin指定しなかった時

Point 2

また、ulpaddingは、アイコンの高さ分余白をとって、被らないように設定しています。
かぶると押せなくなるので、ここで調整してください。

クリックで表示・非表示にする設定

input要素をチェックすることで表示・非表示を切り替えます
ここで設定するのは、メニューの表示と背景の表示です。

手順

  1. <input type="checkbox" id="toggle">で作ったチェックボックス非表示にする
  2. <div>で囲った<nav>要素を表示させるためcheckedでスタイル設定
  3. メニュー表示と同時に、うっすら黒い背景をかぶせるため擬似要素で作成。なおこの背景をクリックすることで、メニューを閉じることができる。(もちろんアイコンクリックでも閉じれる)

Check!
擬似要素で画面いっぱいに背景を重ねることで、どこをタップしてもチェックボックスからチェックが外れ、メニューが閉じるようになります。

header #toggle {
  display: none; /*checkboxは非表示*/
}

/*クリックで表示*/
header #toggle:checked ~ #hidden {
  visibility: visible; /*表示*/
  height: 140px; /*メニューの高さ*/
  overflow-y: scroll; /*溢れた要素はスクロールで見れるように*/
  opacity: 1;
}

/*擬似要素で背景を作りかぶせる*/
header #toggle:checked ~ .close-btn::before {
  content: "";
  position: fixed;

  /*top,left,bottom,right全て0にすることで全画面表示*/
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;

  /*背景色に少し透過させた黒*/
  background: #000;
  opacity: 0.3;

  /*header要素の後ろに*/
  z-index: -1;
}

個人的なメモ
なお、CSSの表記として、#toggleとした箇所はinput[type="checkbox"]と書いても機能する。

ただ、同じページにチェックボックスがあると使えないので、id指定したほうが無難。
どのみちlabelタグで紐づけるため、絶対にid指定するので、cssでもidで設定した方が良いと思われる。

Point

height:140px;としないと、高さのアニメーションが機能せず、ドロップダウンできないので指定しています。

高さを固定したので、メニュー項目が多くなったときにスクロールできるよう、overflow-y: scroll;でスクロール可能に設定しています。

opacityで透明度に関してもアニメーションしているので、すこしだけフワッとでたり消えたりするようになっていますが、好みだと思うのでドロップダウン時に透明度を変化させたくなければopacityの設定はなくてもいいと思います。

+アイコンの設定

fontawesomeなどからとってきたアイコンを表示させてもいいと思います。

が、今回はspanに擬似要素で-を2つ作り、一つはtransform:rotate(90deg);で90度回転させ、かぶせることで+アイコンを作ります。

タップ後は回転させた方の擬似要素をtransform:rotate(0deg);で元の状態に戻し、-の状態にさせています。

視認性を高めるために、+の隣にMenu文字を表示させます。

/*+ボタンのベースとなる部分*/
header .close-btn {
  cursor: pointer;
  z-index: 1;
  height: 0.4em; /*2emからbody{line-height:1.6em;}分を引く*/
  line-height: 2em;
}
 /*Menuの文字 あってもなくても*/
header .close-btn::after {
  position: absolute;
  content: "Menu";
  font-weight: bold;
  top: 0;
  right: 3em; /*+アイコン分余白とる*/
  z-index: 1;
}
/*ボタン部分を擬似要素で作る*/
header .close-btn span::before,
header .close-btn span::after {
  position: absolute;
  content: "";
  width: 1.2em; /*アイコンの大きさ*/
  height: 2px; /*アイコンの太さ*/
  background: #3d3d3d; /*アイコンの色*/
  top: 1em; /*上からの位置*/
  right: 1em; /*右からの位置*/
  transition: all 0.3s ease;
  z-index: 1; /*Menu文字より上に配置*/
}
/*擬似要素の片方は90度回転*/
header .close-btn span::after {
  transform: rotateZ(90deg);
}
/*クリックで回転を0度に*/
header #toggle:checked ~ .close-btn span::after {
  transform: rotate(0deg);
}

これで完成となります。

完成形

See the Pen callback by Micche (@micche) on CodePen.

まとめ

ポイントは、

  1. position:sticky;で上部固定
  2. 擬似要素で+と背景を作る
  3. divnavを包み、ドロップダウン風に動きをつける
  4. チェックボックス駆使

といったとこでしょうか。

どなたかのお役に立てれば幸いです。