【レスポンシブ・アコーディオン付き】Flexboxを駆使したナビゲーションメニューを作成
こんにちは。PeiWebです。
前回の記事に引き続き、Flexboxの復習がてら、ECサイトで使うナビゲーションメニューを実装したので共有します。
完成図
PC
PC版(1500px程度)
タブレット
タブレット版(750px程度)
スマホ
スマホ版(400px程度)
※黒い枠線は関係なし
また、「絞り込み検索」をクリックすると、
アコーディオン実装結果
※黒い枠線は関係なし
上記のような画面になるようにしました。
次に、コードを見ていきます。
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PeiWeb-フレックスボックス</title>
<link rel="stylesheet" href="css/style3.css">
</head>
<body>
<header class="site-header">
<div class="site-header__wrapper">
<div class="wrapper">
<div class="header-left">
<div class="header-facet js-facet">
<p class="header-facet__text">絞り込み検索</p>
</div>
<nav class="nav">
<ul class="nav__wrapper">
<li class="nav__item"><strong>在庫</strong> 在庫あり 在庫なし</li>
<li class="nav__item"><strong>サイズ</strong> S M L</li>
<li class="nav__item"><strong>金額</strong> 0円 <input type="range" name="speed" min="0" max="30000"
step="1000">30,000円 </li>
</ul>
</nav>
</div>
<div class="header-right">
<div class="header-button">
並び替え↓
</div>
</div>
</div>
</div>
</header>
<!-- Header End -->
<script src="js/main3.js"></script>
</body>
</html>
大きいグループで言うと、「絞り込み検索」のクラスとnavタグと「並び替え」のクラスでグループ分けしているようなイメージですかね。。
CSS
body{
margin: 0;
padding: 0;
}
.site-header{
background-color: #def7ff;
}
@media screen and (max-width: 600px) {
.site-header {
border: 1px solid #000;
background-color: #fff;
height: 80px;
}
}
.site-header__wrapper {
margin: 0 auto;
width: 95%;
}
@media screen and (max-width: 600px) {
.site-header__wrapper {
width: 100%;
}
}
.wrapper{
display: flex;
justify-content: flex-end;
gap: 30px;
align-items: center;
}
@media screen and (max-width: 600px) {
.wrapper {
justify-content: center;
gap: 0;
height: 80px;
}
}
.header-left{
display: flex;
align-items: flex-start;
}
@media screen and (max-width: 600px) {
.header-left {
display: block;
border-right: 1px solid #000;
width: 50%;
height: 80px;
}
}
@media screen and (max-width: 600px) {
.nav {
line-height: 0;
height: 0;
overflow: hidden;
opacity: 0;
transition-duration: 0.4s;
}
}
.nav.is-open {
-moz-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid black;
width: 100vw;
line-height: normal;
height: auto;
opacity: 1;
}
.nav__wrapper {
display: flex;
flex-wrap: wrap;
gap: 20px;
list-style-type: none;
}
@media screen and (max-width: 600px) {
.nav__wrapper {
flex-direction: column;
}
}
.header-facet{
position: relative;
}
@media screen and (max-width: 885px) {
.header-facet {
margin: 0;
width: 180px;
text-align: center;
}
}
@media screen and (max-width: 600px) {
.header-facet {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 80px;
font-size: 20px;
}
}
.header-facet::after{
content: "";
position: absolute;
top: 0;
right: -8px;
display: inline-block;
margin: 16px 0;
width: 1px;
height: 20px;
background-color: #030303;
}
@media screen and (max-width: 885px) {
.header-facet::after {
right: 0;
}
}
@media screen and (max-width: 600px) {
.header-facet::after {
background-color: #fff;
}
.header-facet__text::after {
content: "↓";
position: absolute;
top: 24px;
display: inline-block;
}
}
.js-facet.is-active {
background-color: #def7ff;
}
@media screen and (max-width: 600px) {
.header-right {
width: 50%;
height: 80px;
}
}
.header-button {
padding: 5px;
background-color: #eee;
border: 1px solid #000;
}
@media screen and (max-width: 885px) {
.header-button {
width: 100px;
text-align: center;
}
}
@media screen and (max-width: 600px) {
.header-button {
display: flex;
justify-content: center;
align-items: center;
padding: 0;
border: none;
width: 100%;
height: 80px;
font-size: 20px;
background-color: #fff;
}
}
CSSは、flexboxを多用しております。
詳しくは前回の記事で、Flexboxについて記載しているので、そちらをご覧ください。
ご質問ありましたら、TwitterのDMからご質問ください。
JavaScript
const menu = document.querySelectorAll(".js-facet");
function toggle() {
const content = this.nextElementSibling;
this.classList.toggle("is-active");
content.classList.toggle("is-open");
}
for (let i = 0; i < menu.length; i++) {
menu[i].addEventListener("click", toggle);
}
詳しく見ていきます。
querySelectorAll()
指定したセレクターの条件と一致したHTML要素を全て返すメソッドです。
そのため、
const menu = document.querySelectorAll(".js-facet");
クリックする要素であるjs-facetというクラスを取得して、menu
という変数に代入しております。
toggle関数
対象となるHTML要素を簡単に表示・非表示することができる関数です。
今回は、スマホ版で「絞り込み検索」をクリックするごとに、「表示」「非表示」を繰り返してほしいので、toggle関数にしております。中身を見ていきます。
nextElementSibling
「nextElementSibling」は次の要素を取得するプロパティです。
ここでは、
const content = this.nextElementSibling;
上記のように書き、「nextElementSibling」でthis(直前の要素である'「js-facet」')の隣の要素である'「nav」'を取得しております。(下記のコード参照)
この'navクラス'をcontentという変数に代入しています。
<!-- 「js-facet」の要素 -->
<div class="header-facet js-facet">
<p class="header-facet__text">絞り込み検索</p>
</div>
<!-- 「js-facet」の隣の要素 -->
<nav class="nav">
<ul class="nav__wrapper">
<li class="nav__item"><strong>在庫</strong> 在庫あり 在庫なし</li>
<li class="nav__item"><strong>サイズ</strong> S M L</li>
<li class="nav__item"><strong>金額</strong> 0円 <input type="range" name="speed" min="0" max="30000"
step="1000">30,000円 </li>
</ul>
</nav>
classList
特定の要素のクラス名を追加したり、削除したり、参照したりすることが出来る便利なプロパティです。classListにはいくつかメソッドがあるため、下記に記載します。
メソッド | 説明 |
---|---|
add | 該当する要素にクラスを追加 |
remove | 該当する要素にクラスを削除 |
contains | 該当する要素にクラスがあるか確認 |
toggle | 該当する要素にクラスがあれば削除、なければ追加する |
ここでは、toggleメソッドを用いて以下のように記述しております。
this.classList.toggle("is-active");
content.classList.toggle("is-open");
つまり、
this(js-facet)のクラスに、is-active
クラスを追加・削除
content(nav)のクラスに、is-open
クラスを追加・削除
を行っております。
addEventListener
マウスによるクリックやキーボードからの入力といった様々なイベント処理を実行するメソッドです。
// 書き方
対象の要素.addEventListener(イベント名, 関数, false(省略可));
第1引数にイベントの種類、第2引数に関数、第3引数にイベント伝搬の方式をtrueかfalseで指定、第3引数は通常はfalseを指定します。
イベント名を一部紹介します。
イベント名 | 説明 |
---|---|
click | マウスボタンをクリックしたとき |
scroll | 画面がスクロールしたとき |
mousedown | マウスボタンを押しているとき |
mouseup | マウスボタンを離したとき |
mousemove | マウスカーソルが移動したとき |
keydown | キーボードのキーを押したとき |
keyup | キーボードのキーを離したとき |
keypress | キーボードのキーを押しているとき |
今回は、下記のようにfor文を使って要素にクリックイベントをつくりました。
for (let i = 0; i < menu.length; i++) {
menu[i].addEventListener("click", toggle);
}
これで、「絞り込み検索」を押したときにナビゲーションメニューが表示されるようになりました!
こんな感じで実装完了ですね^^
最後に、、、
少しでも参考になれば記事にイイねしていただけますと嬉しいです。
Webサイト & ECサイト構築のご相談・ご依頼はTwitterのDMまでお願いいたします!
お待ちしております^^
Discussion