こんにちは!株式会社プロットハブのエンジニア、山名です。
ホームページに欠かせないヘッダー要素だけど、大体の形は一緒だし毎回作るのも面倒くさい!
しかもハンバーガーメニューはJavaScriptやjQueryをちょっと触らないといけないからさらに面倒!そんなあなたに!
今回は案件でも使用した(実際の案件ではTailwind CSSを使用して作成)追従型のヘッダーを通常のHTMLコーディングでも使いやすい様に再編集してご紹介します!
clampを使ってレスポンシブ対応でコピペでそのまご使用いただけると思いますのでよかったら使ってね。
HTMLの記述
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- お好きなCSSを読み込んでください -->
</head>
<body>
<!-- レスポンシブ込みの追従ヘッダー -->
<header class="header">
<div class="header-container">
<h1 class="header-logo">
<a href="#" id="logo" class="logo-link">
<img src="https://plot-hub.com/code_example/lib/img/logo.jpg" alt="">
</a>
</h1>
<nav id="hb-menu" class="nav-menu">
<ul class="menu-list">
<li class="menu-item"><a href="#" class="menu-link">MENU1</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU2</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU3</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU4</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU5</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU6</a></li>
</ul>
</nav>
<!-- ハンバーガーメニュー ボタン -->
<button id="openbtn" class="hamburger-button">
<div class="hamburger-lines">
<span class="line"></span>
<span class="line"></span>
</div>
</button>
<!-- ハンバーガーメニュー ボタン ここまで -->
</div>
</header>
<!-- レスポンシブ込みの追従ヘッダー ここまで -->
</body>
</html>
CSSの記述
ブレイクポイントは1024pxと768px以下でデバイスが横になった時に切り替わります。
clampを使って切り替えているのでどのデバイスで見ても大体ちょうどいいサイズになっていると思います。
ちなみに1025px以上のサイズはビューポート1920pxをベースに、1024px以下では375pxをベースに、768px以下かつデバイスが横の場合は667pxをベースにvwを算出しています。
<style media="screen">
header {
position: fixed;
z-index: 10;
top: 0;
right: 0;
left: 0;
width: 100%;
max-width: 1920px;
margin-left: auto;
margin-right: auto;
padding: clamp(20px, 5.333333333333333vw, 40px);
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
}
@media (min-width: 1025px) {
header {
padding: clamp(30px, 3.125vw, 60px) clamp(40px, 4.6875vw, 90px);
}
}
@media (max-width: 768px) and (orientation: landscape) {
header {
padding: clamp(10px, 2.998500749625187vw, 20px);
}
}
.header-container {
display: -ms-grid;
display: grid;
-webkit-box-align: center;
align-items: center;
-ms-flex-align: center;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-ms-grid-columns: 1fr 2fr;
grid-template-columns: 1fr 2fr;
}
.header-logo {
width: -moz-fit-content;
width: -webkit-fit-content;
width: fit-content;
}
@media (max-width: 768px) and (orientation: landscape) {
.header-logo {
width: clamp(70px, 17.991004497751124vw, 140px);
}
}
.logo-link {
display: block;
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
}
.logo-link:hover {
opacity: 0.6;
}
@media (max-width: 1024px) {
.nav-menu {
position: fixed;
z-index: -1;
top: 0;
right: 0;
width: 100%;
height: 100vh;
height: calc(var(--vh, 1vh) * 100);
padding-right: clamp(30px, 8vw, 60px);
padding-bottom: clamp(30px, 8vw, 60px);
padding-left: clamp(30px, 8vw, 60px);
transition-duration: 300ms;
transform: translateX(200%);
overflow: auto;
/* ナビメニューの背景色を変えたい時 */
background-color: rgba(0, 0, 0, .6);
}
.nav-menu.active {
transform: translateX(0);
}
}
@media (min-width: 1025px) {
.nav-menu {
padding-top: 0 !important;
}
}
@media (min-width: 1025px) {
.menu-list {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
align-items: center;
-ms-flex-align: center;
-webkit-box-pack: end;
-ms-flex-pack: end;
justify-content: flex-end;
gap: clamp(20px, 2.0833333333333335vw, 40px);
}
}
@media (max-width: 1024px) {
.menu-item {
/* 各ナビメニューの下線を変えたい時 */
border-style: solid;
border-color: #fff;
border-bottom-width: 1px;
}
}
.menu-link {
display: block;
color: #000;
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
}
.menu-link:hover {
opacity: 0.6;
}
.nav-menu.active .menu-link {
color: #fff;
}
@media (max-width: 1024px) {
.menu-link {
font-size: clamp(14px, 1.0416666666666667vw, 20px);
padding-top: clamp(10px, 2.6666666666666665vw, 20px);
padding-bottom: clamp(10px, 2.6666666666666665vw, 20px);
text-align: center;
/* ナビメニューの文字色を変えたい時 */
color: #000;
}
}
@media (min-width: 1025px) {
.menu-link {
font-size: clamp(14px, 1.0416666666666667vw, 20px);
}
}
.hamburger-button {
width: -moz-fit-content;
width: -webkit-fit-content;
width: fit-content;
height: clamp(13px, 3.466666666666667vw, 26px);
margin-right: 0;
margin-left: auto;
cursor: pointer;
}
.hamburger-lines {
position: relative;
width: clamp(40px, 10.666666666666666vw, 90px);
height: clamp(13px, 3.466666666666667vw, 26px);
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
}
@media (max-width: 1024px) {
.hamburger-lines {
width: clamp(40px, 10.666666666666666vw, 90px);
height: clamp(13px, 3.466666666666667vw, 26px);
}
}
@media (max-width: 768px) and (orientation: landscape) {
.hamburger-lines {
width: clamp(30px, 7.496251874062969vw, 50px);
height: clamp(15px, 2.998500749625187vw, 20px);
}
}
.hamburger-lines.active {
height: 1px;
}
.hamburger-lines .line {
position: absolute;
right: 0;
left: 0;
display: block;
width: 100%;
height: clamp(1px, .26666666666666666vw, 2px);
margin: auto;
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
/* ハンバーガーメニューの線の色を変えたい時 */
background-color: #000;
}
.hamburger-lines.active .line {
/* ハンバーガーメニューオープン時の線の色を変えたい時 */
background-color: #fff;
}
.hamburger-lines .line:nth-child(1) {
top: 0;
}
.hamburger-lines .line:nth-child(2) {
bottom: 0;
}
@media (min-width: 1025px) {
/* タブレットサイズ以上でハンバーガーメニューを丸ごと非表示 */
.hamburger-button {
display: none;
}
}
</style>
jQueryの記述
不要なもの、必要なものは案件によって変わると思うので汎用的なもののみ記載しています。
ブレイクポイントで切り替わった際、ヘッダーの高さも変わると思うのでウィンドウのリサイズ時にもヘッダーの高さを再取得する処理も入れています。
// jQueryのCDNを読み込み
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function($) {
// ヘッダーの高さを代入する処理
function setHeaderHeights() {
var commonHeaderHeight = $("header").outerHeight();
// ハンバーガーメニューの上部にheaderの高さ分の余白をつける
$("#hb-menu").css("padding-top", commonHeaderHeight + "px");
}
// リサイズ時にもsetHeaderHeightsを実行
$(window).on('resize', function() {
setHeaderHeights();
});
// setHeaderHeightsを実行
setHeaderHeights();
// ハンバーガーメニューのクリック処理
$('#openbtn').on('click', function() {
$(this).toggleClass('active'); // ボタン自身に.activeクラスをトグル
$('#hb-menu').toggleClass('active', $(this).hasClass('active')); // ハンバーガーメニューに.activeクラスをトグル
if ($(this).hasClass('active')) {
// ハンバーガーメニューがアクティブな場合の処理
$('#openbtn .hamburger-lines').addClass('active');
$('#openbtn .hamburger-lines .line:nth-child(1)').css('width', '60%'); // 上の線の幅を60%に設定
$('#openbtn .hamburger-lines .line:nth-child(2)').css('width', '60%'); // 下の線の幅を60%に設定
setTimeout(function() {
// 交差させるために、上の線を下に、下の線を上に移動し、45度回転させる
$('#openbtn .hamburger-lines .line:nth-child(1)').css('bottom', '0').css('transform', 'rotate(45deg)');
$('#openbtn .hamburger-lines .line:nth-child(2)').css('top', '0').css('transform', 'rotate(-45deg)');
}, 300); // 300ミリ秒後に実行
} else {
// ハンバーガーメニューが非アクティブな場合の処理
$('#openbtn .hamburger-lines .line:nth-child(1)').css('transform', 'rotate(0deg)').css('bottom', 'auto'); // 上の線の回転と位置を元に戻す
$('#openbtn .hamburger-lines .line:nth-child(2)').css('transform', 'rotate(0deg)').css('top', 'auto'); // 下の線の回転と位置を元に戻す
setTimeout(function() {
$('#openbtn .hamburger-lines .line:nth-child(1)').css('width', '100%'); // 上の線の幅を元に戻す
$('#openbtn .hamburger-lines .line:nth-child(2)').css('width', '100%'); // 下の線の幅を元に戻す
$('#openbtn .hamburger-lines').removeClass('active'); // .hamburger-linesから.activeクラスを除去
}, 300); // 300ミリ秒後に実行
}
});
});
</script>
全体の記述
<meta name="robots" content="noindex,nofollow" />
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://plot-hub.com/code_example/lib/css/reset.css">
<style media="screen">
header {
position: fixed;
z-index: 10;
top: 0;
right: 0;
left: 0;
width: 100%;
max-width: 1920px;
margin-left: auto;
margin-right: auto;
padding: clamp(20px, 5.333333333333333vw, 40px);
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
}
@media (min-width: 1025px) {
header {
padding: clamp(30px, 3.125vw, 60px) clamp(40px, 4.6875vw, 90px);
}
}
@media (max-width: 768px) and (orientation: landscape) {
header {
padding: clamp(10px, 2.998500749625187vw, 20px);
}
}
.header-container {
display: -ms-grid;
display: grid;
-webkit-box-align: center;
align-items: center;
-ms-flex-align: center;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-ms-grid-columns: 1fr 2fr;
grid-template-columns: 1fr 2fr;
}
.header-logo {
width: -moz-fit-content;
width: -webkit-fit-content;
width: fit-content;
}
@media (max-width: 768px) and (orientation: landscape) {
.header-logo {
width: clamp(70px, 17.991004497751124vw, 140px);
}
}
.logo-link {
display: block;
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
}
.logo-link:hover {
opacity: 0.6;
}
@media (max-width: 1024px) {
.nav-menu {
position: fixed;
z-index: -1;
top: 0;
right: 0;
width: 100%;
height: 100vh;
height: calc(var(--vh, 1vh) * 100);
padding-right: clamp(30px, 8vw, 60px);
padding-bottom: clamp(30px, 8vw, 60px);
padding-left: clamp(30px, 8vw, 60px);
transition-duration: 300ms;
transform: translateX(200%);
overflow: auto;
/* ナビメニューの背景色を変えたい時 */
background-color: rgba(0, 0, 0, .6);
}
.nav-menu.active {
transform: translateX(0);
}
}
@media (min-width: 1025px) {
.nav-menu {
padding-top: 0 !important;
}
}
@media (min-width: 1025px) {
.menu-list {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
align-items: center;
-ms-flex-align: center;
-webkit-box-pack: end;
-ms-flex-pack: end;
justify-content: flex-end;
gap: clamp(20px, 2.0833333333333335vw, 40px);
}
}
@media (max-width: 1024px) {
.menu-item {
/* 各ナビメニューの下線を変えたい時 */
border-style: solid;
border-color: #fff;
border-bottom-width: 1px;
}
}
.menu-link {
display: block;
color: #000;
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
}
.menu-link:hover {
opacity: 0.6;
}
.nav-menu.active .menu-link {
color: #fff;
}
@media (max-width: 1024px) {
.menu-link {
font-size: clamp(14px, 1.0416666666666667vw, 20px);
padding-top: clamp(10px, 2.6666666666666665vw, 20px);
padding-bottom: clamp(10px, 2.6666666666666665vw, 20px);
text-align: center;
/* ナビメニューの文字色を変えたい時 */
color: #000;
}
}
@media (min-width: 1025px) {
.menu-link {
font-size: clamp(14px, 1.0416666666666667vw, 20px);
}
}
.hamburger-button {
width: -moz-fit-content;
width: -webkit-fit-content;
width: fit-content;
height: clamp(13px, 3.466666666666667vw, 26px);
margin-right: 0;
margin-left: auto;
cursor: pointer;
}
.hamburger-lines {
position: relative;
width: clamp(40px, 10.666666666666666vw, 90px);
height: clamp(13px, 3.466666666666667vw, 26px);
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
}
@media (max-width: 1024px) {
.hamburger-lines {
width: clamp(40px, 10.666666666666666vw, 90px);
height: clamp(13px, 3.466666666666667vw, 26px);
}
}
@media (max-width: 768px) and (orientation: landscape) {
.hamburger-lines {
width: clamp(30px, 7.496251874062969vw, 50px);
height: clamp(15px, 2.998500749625187vw, 20px);
}
}
.hamburger-lines.active {
height: 1px;
}
.hamburger-lines .line {
position: absolute;
right: 0;
left: 0;
display: block;
width: 100%;
height: clamp(1px, .26666666666666666vw, 2px);
margin: auto;
-webkit-transition-duration: 300ms;
transition-duration: 300ms;
/* ハンバーガーメニューの線の色を変えたい時 */
background-color: #000;
}
.hamburger-lines.active .line {
/* ハンバーガーメニューオープン時の線の色を変えたい時 */
background-color: #fff;
}
.hamburger-lines .line:nth-child(1) {
top: 0;
}
.hamburger-lines .line:nth-child(2) {
bottom: 0;
}
@media (min-width: 1025px) {
/* タブレットサイズ以上でハンバーガーメニューを丸ごと非表示 */
.hamburger-button {
display: none;
}
}
</style>
</head>
<body>
<!-- レスポンシブ込みの追従ヘッダー -->
<header class="header">
<div class="header-container">
<h1 class="header-logo">
<a href="#" id="logo" class="logo-link">
<img src="https://plot-hub.com/code_example/lib/img/logo.jpg" alt="">
</a>
</h1>
<nav id="hb-menu" class="nav-menu">
<ul class="menu-list">
<li class="menu-item"><a href="#" class="menu-link">MENU1</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU2</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU3</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU4</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU5</a></li>
<li class="menu-item"><a href="#" class="menu-link">MENU6</a></li>
</ul>
</nav>
<!-- ハンバーガーメニュー ボタン -->
<button id="openbtn" class="hamburger-button">
<div class="hamburger-lines">
<span class="line"></span>
<span class="line"></span>
</div>
</button>
<!-- ハンバーガーメニュー ボタン ここまで -->
</div>
</header>
<!-- レスポンシブ込みの追従ヘッダー ここまで -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function($) {
// ヘッダーの高さを代入する処理
function setHeaderHeights() {
var commonHeaderHeight = $("header").outerHeight();
// ハンバーガーメニューの上部にheaderの高さ分の余白をつける
$("#hb-menu").css("padding-top", commonHeaderHeight + "px");
}
// リサイズ時にもsetHeaderHeightsを実行
$(window).on('resize', function() {
setHeaderHeights();
});
setHeaderHeights();
// ハンバーガーメニューのクリック処理
$('#openbtn').on('click', function() {
$(this).toggleClass('active'); // ボタン自身に.activeクラスをトグル
$('#hb-menu').toggleClass('active', $(this).hasClass('active')); // ハンバーガーメニューに.activeクラスをトグル
if ($(this).hasClass('active')) {
// ハンバーガーメニューがアクティブな場合の処理
$('#openbtn .hamburger-lines').addClass('active');
$('#openbtn .hamburger-lines .line:nth-child(1)').css('width', '60%'); // 上の線の幅を60%に設定
$('#openbtn .hamburger-lines .line:nth-child(2)').css('width', '60%'); // 下の線の幅を60%に設定
setTimeout(function() {
// 交差させるために、上の線を下に、下の線を上に移動し、45度回転させる
$('#openbtn .hamburger-lines .line:nth-child(1)').css('bottom', '0').css('transform', 'rotate(45deg)');
$('#openbtn .hamburger-lines .line:nth-child(2)').css('top', '0').css('transform', 'rotate(-45deg)');
}, 300); // 300ミリ秒後に実行
} else {
// ハンバーガーメニューが非アクティブな場合の処理
$('#openbtn .hamburger-lines .line:nth-child(1)').css('transform', 'rotate(0deg)').css('bottom', 'auto'); // 上の線の回転と位置を元に戻す
$('#openbtn .hamburger-lines .line:nth-child(2)').css('transform', 'rotate(0deg)').css('top', 'auto'); // 下の線の回転と位置を元に戻す
setTimeout(function() {
$('#openbtn .hamburger-lines .line:nth-child(1)').css('width', '100%'); // 上の線の幅を元に戻す
$('#openbtn .hamburger-lines .line:nth-child(2)').css('width', '100%'); // 下の線の幅を元に戻す
$('#openbtn .hamburger-lines').removeClass('active'); // .hamburger-linesから.activeクラスを除去
}, 300); // 300ミリ秒後に実行
}
});
});
</script>
</body>
</html>
実際の表示を確認
実際のレイアウトはこちらからご確認いただけます。→https://plot-hub.com/code_example/546/
検証モードなどで確認してみてください。
終わりに
今回はコピペで簡単に使えるハンバーガーメニュー込みのレスポンシブな追従型ヘッダーをご紹介しましたが、いかがだったでしょうか?
CSSのclamp処理に関してはこちらの記事(TailwindCSSにVWとClampを実装する)でもお伝えしているTialwindCSS+clampカスタマイズを使用して算出された値を再編集して記載しています。
よければそちらもご覧ください。
皆さんに意見もらってどんどんブラッシュアップできればと思っているのでコメントお待ちしています!
それではまた!
コメント