追従するグローバルメニュー【CSSのみ】
グローバルメニューっていうのは、当ブログにあるようなこれ↓
とか、これ↓
のようなメニューのこと。
こんな感じのメニューを画面上部に追従させて、クリックしたら表示、クリックで非表示するようにします。
全部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で見れます。
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
header
内に、h1
、div
を収納。h1
にはサイトタイトルとヘッダーの背景を設定。div
には、+
アイコンと、クリック(タップ)で表示・非表示する要素(今回はグローバルメニュー用のnav
要素)を入れる
CSSの設定
最終的に↓の画像のようになります。
Menu +
を押すことでメニューが表示され、さらにスクロールしても上部に固定されるようにします。
position:sticky;
を使用します。
- header部分の設定
- 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;
が聞いちゃって、メニューがどっかいっちゃうので、設定しておきます。
/*メニュー部分*/ 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;
は、+アイコンのサイズ分上にあげる設定です。
これをしないと不自然に隙間が空くので設定しています。
Point 2
また、ul
のpadding
は、アイコンの高さ分余白をとって、被らないように設定しています。
かぶると押せなくなるので、ここで調整してください。
クリックで表示・非表示にする設定
input
要素をチェックすることで表示・非表示を切り替えます。
ここで設定するのは、メニューの表示と背景の表示です。
手順
<input type="checkbox" id="toggle">
で作ったチェックボックスを非表示にする<div>
で囲った<nav>
要素を表示させるため、checked
でスタイル設定- メニュー表示と同時に、うっすら黒い背景をかぶせるため擬似要素で作成。なおこの背景をクリックすることで、メニューを閉じることができる。(もちろんアイコンクリックでも閉じれる)
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
で設定した方が良いと思われる。
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.
まとめ
ポイントは、
position:sticky;
で上部固定- 擬似要素で
+
と背景を作る div
でnav
を包み、ドロップダウン風に動きをつける- チェックボックス駆使
といったとこでしょうか。
どなたかのお役に立てれば幸いです。