【コードサンプル】パネル形式・イメージ画像表示の「メガメニュー」

ドロップダウン形式のグローバルナビメニューをカスタマイズして、パネル形式&イメージ画像を表示できるメガメニューのコードサンプルを作ってみました。
リンクごとに画像を表示するので、商品カテゴリーなど、ユーザーに訴えかけたいECサイトなどで有効なレイアウトです。
目次
動作の確認
2階層構造のグローバルメニューで、親階層のリンク部分にマウスオンすると、ドロップダウンで子階層が表示され、子階層は、グリッドデザインのリンク部分と、マウスオンでさらに各リンクに設定した画像が表示される仕様になります。

コードサンプルの確認
「HTML」、「CSS」、「JavaScript(jQuery)」の各コードは次の通りです。
HTMLのマークアップ
<nav id="gnav">
<ul>
<li>
<a href="">Menu1</a>
<div class="gnav_child">
<div class="container">
<ul>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/cloth01.jpg)"><span>Child01</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/cloth02.jpg)"><span>Child02</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/cloth03.jpg)"><span>Child03</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/cloth04.jpg)"><span>Child04</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/cloth05.jpg)"><span>Child05</span></a></li>
</ul>
<div class="image_area"><span></span></div>
</div>
</div>
</li>
<li>
<a href="">Menu2</a>
<div class="gnav_child">
<div class="container">
<ul>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/bag01.jpg)"><span>Child01</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/bag02.jpg)"><span>Child02</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/bag03.jpg)"><span>Child03</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/bag04.jpg)"><span>Child04</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/bag05.jpg)"><span>Child05</span></a></li>
</ul>
<div class="image_area"><span></span></div>
</div>
</div>
</li>
<li>
<a href="">Menu3</a>
<div class="gnav_child">
<div class="container">
<ul>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/shoes01.jpg)"><span>Child01</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/shoes02.jpg)"><span>Child02</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/shoes03.jpg)"><span>Child03</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/shoes04.jpg)"><span>Child04</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/shoes05.jpg)"><span>Child05</span></a></li>
</ul>
<div class="image_area"><span></span></div>
</div>
</div>
</li>
<li>
<a href="">Menu4</a>
<div class="gnav_child">
<div class="container">
<ul>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/watch01.jpg)"><span>Child01</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/watch02.jpg)"><span>Child02</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/watch03.jpg)"><span>Child03</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/watch04.jpg)"><span>Child04</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/watch05.jpg)"><span>Child05</span></a></li>
</ul>
<div class="image_area"><span></span></div>
</div>
</div>
</li>
<li>
<a href="">Menu5</a>
<div class="gnav_child">
<div class="container">
<ul>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/hat01.jpg)"><span>Child01</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/hat02.jpg)"><span>Child02</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/hat03.jpg)"><span>Child03</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/hat04.jpg)"><span>Child04</span></a></li>
<li><a href="" data-img="url(https://web-basic-archive.site/test/img/hat05.jpg)"><span>Child05</span></a></li>
</ul>
<div class="image_area"><span></span></div>
</div>
</div>
</li>
</ul>
</nav>子階層の部分のポイントとなるのは次の通りです。
- 子階層(.gnav_child)は、.container で包み、パネル形式のリンク部分の ul とイメージ画像を表示する .image_area に分かれます。
- 各リンクごとのイメージ画像の設定は、a要素に 「data-img」 というdata属性を作成し、この値に画像のパスを設定しておきます。JavaScriptでこの値を取得し、.image_area の背景画像にセットします。
- 画像を表示する .image_area は中に span要素を持った2重構造にしておきます。
CSSスタイリング
/*グローバルナビメニュー*/
#gnav ul {
list-style: none;
padding-left: 0;
}
#gnav ul li a {
text-decoration: none;
display: block;
width: 100%;
height: 100%;
color: var(--link-color);
text-align: center;
position: relative;
}
/*親階層の設定*/
#gnav>ul {
display: flex;
}
#gnav>ul>li {
width: 6rem;
padding: 10px 0;
}
#gnav>ul>li>a {
padding: 5px 10px;
}
/* 親階層リンク マウスオンでテキスト色変更アニメーション */
#gnav>ul:hover>li>a {
color: #ccc;
}
#gnav>ul:hover>li:hover>a {
color: var(--link-color);
}
/* 親階層リンクのマウスオンアンダーバー */
#gnav>ul>li>a::before {
content: "";
position: absolute;
bottom: 0;
left: 50%;
width: 80%;
height: 2px;
border-radius: 5px;
background: var(--link-color);
transition: all .5s cubic-bezier(0.075, 0.82, 0.165, 1);
transform: translateX(-50%) scaleX(0);
opacity: 0;
}
#gnav>ul>li:hover a::before {
opacity: 1;
transform: translateX(-50%) scaleX(1);
}
/*子階層*/
.gnav_child {
visibility: hidden;
width: 100vw;
height: 500px;
position: absolute;
left: 0;
top: calc(100% - 20px);
background: #fff;
-webkit-box-shadow: 0px 3px 10px 2px rgba(25, 26, 26, 0.3);
box-shadow: 0px 3px 10px 2px rgba(25, 26, 26, 0.3);
z-index: 0;
transition: all .5s cubic-bezier(0.075, 0.82, 0.165, 1);
transform: scaleY(0);
transform-origin: center top;
opacity: 0;
}
/*子階層ドロップダウン*/
#gnav>ul>li:hover .gnav_child {
visibility: visible;
opacity: 1;
transform: scaleY(1);
}
/*子階層のレイアウト設定*/
.gnav_child .container {
max-width: 1280px; /*レイアウトに合わせてサイズを変更してください*/
height: 100%;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1fr; /*PCサイズではリンクと画像は左右で表示*/
grid-template-rows: 1fr;
grid-column-gap: 10px;
grid-row-gap: 10px;
}
/*子階層リンク部分*/
.gnav_child ul {
padding: 10px;
margin-left: 10px;
display: grid;
grid-template-columns: 1fr 1fr 1fr; /*グリッドパネル表示 このサンプルでは3×3マス設定*/
grid-template-rows: 1fr 1fr 1fr;
grid-column-gap: 10px;
grid-row-gap: 10px;
}
#gnav .gnav_child ul li a {
padding: 10px 5px;
font-size: 1.3rem;
display: flex;
justify-content: center; /*リンクテキストはパネルの中央に表示*/
align-items: center;
background: #eee;
border-radius: 5px;
transition: all .5s cubic-bezier(0.075, 0.82, 0.165, 1);
}
#gnav .gnav_child ul li a:hover {
background: var(--link-color); /*マウスオンでカラー変更*/
color: #fff;
}
/*子階層 イメージ画像エリアの設定*/
.image_area {
background-color: #eee;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
.image_area span {
display: block;
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
/*モバイル表示*/
@media screen and (max-width:767px) {
#gnav>ul>li {
width: auto;
}
.gnav_child .container { /*モバイルの場合はリンクと画像は上下にレイアウト変更*/
width: 100vw;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
grid-column-gap: 0;
grid-row-gap: 0;
padding-left: 0;
}
}
各ポイントとなる部分を解説します。
親階層マウスオンでリンクカラー変更・アンダーバー表示

メガメニューの場合、ドロップダウンする子階層メニューは、画面いっぱいに広がって表示されるので、どの親階層のリンクの子階層なのかがわかりにくい状態になります。ユーザービリティを考慮して、現在どの親階層リンクを選択(マウスオン状態)しているのか、わかるようにマークしていきます。
選択していない(マウスが乗っていない)、未選択のリンクは薄いグレーに変更。また同時に、リンクの下部分にバーをアニメーション表示して、目立たせています。
当該部分のCSSは以下の通りです。
/* 親階層リンク マウスオンでテキスト色変更アニメーション */
#gnav>ul:hover>li>a {
color: #ccc;
}
#gnav>ul:hover>li:hover>a {
color: var(--link-color);
}
/* 親階層リンクのマウスオンアンダーバー */
#gnav>ul>li>a::before {
content: "";
position: absolute;
bottom: 0;
left: 50%;
width: 80%;
height: 2px;
border-radius: 5px;
background: var(--link-color);
transition: all .5s cubic-bezier(0.075, 0.82, 0.165, 1);
transform: translateX(-50%) scaleX(0);
opacity: 0;
}
#gnav>ul>li:hover a::before {
opacity: 1;
transform: translateX(-50%) scaleX(1);
}子階層レイアウト設定はgridを使用

リンク部分とイメージ画像のレイアウトは、それぞれ grid を使用しています。
ウィンドウサイズによって、左右のレイアウトを上下に変更することで見やすさに対応。また、パネル部分は、3×3のグリッドにしていますが、ページ数やデザインによってカスタマイズしてください。
/*子階層のレイアウト設定*/
.gnav_child .container {
max-width: 1280px; /*レイアウトに合わせてサイズを変更してください*/
height: 100%;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1fr; /*PCサイズではリンクと画像は左右で表示*/
grid-template-rows: 1fr;
grid-column-gap: 10px;
grid-row-gap: 10px;
}
/*モバイル表示*/
@media screen and (max-width:767px) {
.gnav_child .container { /*モバイルの場合はリンクと画像は上下にレイアウト変更*/
width: 100vw;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
grid-column-gap: 0;
grid-row-gap: 0;
padding-left: 0;
}
}
/*子階層リンク部分*/
.gnav_child ul {
padding: 10px;
margin-left: 10px;
display: grid;
grid-template-columns: 1fr 1fr 1fr; /*グリッドパネル表示 このサンプルでは3×3マス設定*/
grid-template-rows: 1fr 1fr 1fr;
grid-column-gap: 10px;
grid-row-gap: 10px;
}JavaScript(jQuery)のプログラム
HTMLの構造の部分でも触れましたが、子階層のリンク部分にマウスオンすると紐づけられたイメージ画像が表示されるように、jQueryを使用して制御しています。
今回リンクと画像の紐づけは、a要素にdata属性を作成し、そこに画像のパスを設定する方法を取りました。
a要素にmouseoverでパスを取得、イメージ画像エリアのbackgound-imageのパスにその値を設定するという内容です。
ですがこのままでは、親階層にマウスオンした状態で子階層のリンク部分にさらにマウスオンするまでの間、イメージ画像が何も表示されない状態になってしまい、印象が悪くなってしまいます。
それを解消するために、子階層の最初のリンク要素(first-child)の画像を取得し、表示するように設定を行いました。こちらは、親階層のliにマウスオンした状態で発動するように設定したかったので上記の設定と一部バッティングしてしまい、対応策として表示するイメージ画像エリアの構造を2重にし、それぞれの画像を表示するように改善しました。

$(function () {
// マウスオンでイメージ画像を表示
//親階層のliにマウスオンした時点で子階層の最初のリンクに設定した画像を表示する
$('#gnav ul li').hover(
function(){
const first_img = $(this).find('.gnav_child li:first-child a').attr("data-img");
$('.image_area').css('background-image', first_img);
},
function(){
$('.image_area span').css('background-image', 'none');
}
)
//子階層のリンク部分にマウスオンで画像を表示
$('.gnav_child a').mouseover(function () {
const img_url = $(this).attr("data-img"); //a要素に作成したdata-imgプロパティに設定した画像のURLを変数にセット
if (img_url) {
$('.image_area span').css('background-image', img_url); //画像を表示するimage_areaの背景画像のパスに設定
}
else {
$('.image_area span').css('background-image', 'none');
}
});
});全体のコードサンプル
全体のコードは次のようになります。
See the Pen Mega menu - Panel + Image by web-basic-archive (@web-basic-archive) on CodePen.
まだまだコーディングに未熟なところもありますが、参考に使っていただければ幸いです。


