🙌
スクロールすると表示・非表示が切り替わるヘッダーのテンプレート | HTML, CSS(SCSS), JS
概要
スクロールすると表示・非表示が切り替わるヘッダーのテンプレート. 下にスクロールすると、ヘッダーが画面上部に消えていって、上にバックスクロールすると、ヘッダーが画面上部から出現する
よく使うのでテンプレートにしました
サンプルページ
前提
ファイル構造
/
├ logo-256x512.png
├ index.html
├ style.css
└ script.js
コード
HTML / index.html
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sample</title>
<link rel="stylesheet" href="./style.css">
<script src="./script.js"></script>
</head>
<body>
<!-- ここから -->
<header>
<div class="header-wrap">
<div class="header-logo">
<a href="#">
<img src="./logo-256x512.png" alt="Sample Header Logo Image" />
</a>
</div>
<div class="header-menu">
<nav>
<li><a href="#">メニュー1</a></li>
<li><a href="#">メニュー2</a></li>
</nav>
</div>
</div>
</header>
<!-- ここまでが必要 -->
</body>
</html>
CSS / style.css
style.css
* {
margin: 0;
padding: 0;
box-sizing: content-box;
}
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: black;
height: 50px;
}
header * {
transition: 0.4s;
}
header li, header a {
list-style: none;
color: white;
text-decoration: none;
}
header.hide {
animation: headerFadeOut 1s;
opacity: 0;
}
header.show {
opacity: 1;
animation: headerFadeIn 1s;
}
.header-wrap {
height: 100%;
display: flex;
}
.header-logo, .header-logo * {
height: 100%;
}
.header-logo a {
display: flex;
align-items: center;
text-align: center;
}
.header-logo a:hover {
opacity: 0.6;
}
.header-menu {
flex-grow: 10;
display: flex;
justify-content: space-between;
}
.header-menu nav {
display: flex;
}
.header-menu li {
display: flex;
align-items: center;
margin: 0 0.5rem;
}
.header-menu a:hover {
opacity: 0.6;
}
@keyframes headerFadeOut {
0% {
opacity: 1;
top: 0;
}
100% {
opacity: 0;
top: -100%;
}
}
@keyframes headerFadeIn {
0% {
top: -100%;
}
100% {
top: 0;
}
}/*# sourceMappingURL=style.css.map */
SCSS からコンバートしたもの. ソースは以下
SCSS ソースコード
style.scss
@charset "UTF-8";
// ヘッダーの表示・非表示アニメーションにかける時間
$HEADER-ANIMATION-DURATION: 1s;
// ヘッダーの高さ
$HEADER-HEIGHT: 50px;
* {
margin: 0;
padding: 0;
box-sizing: content-box;
}
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: black;
height: $HEADER-HEIGHT;
* {
transition: .4s;
}
li, a {
list-style: none;
color: white;
text-decoration: none;
}
&.hide {
animation: headerFadeOut $HEADER-ANIMATION-DURATION;
opacity: 0;
}
&.show {
opacity: 1;
animation: headerFadeIn $HEADER-ANIMATION-DURATION;
}
}
.header-wrap {
height: 100%;
display: flex;
}
.header-logo {
&, * {
height: 100%;
}
a {
display: flex;
align-items: center;
text-align: center;
&:hover {
opacity: .6;
}
}
}
.header-menu {
flex-grow: 10;
display: flex;
justify-content: space-between;
nav {
display: flex;
}
li {
display: flex;
align-items: center;
margin: 0 .5rem;
}
a {
&:hover {
opacity: .6;
}
}
}
@keyframes headerFadeOut {
0% {
opacity: 1;
top: 0;
}
100% {
opacity: 0;
top: -100%;
}
}
@keyframes headerFadeIn {
0% {
top: -100%;
}
100% {
top: 0;
}
}
JS / script.js
script.js
const CONSTS = {
/**
* ヘッダーの表示・非表示アニメーションにかける時間
* style.scss の HEADER-ANIMATION-DURATION と同じ秒数を指定する
* @type {Number} 単位: ミリ秒
*/
HEADER_ANIMATION_DURATION: 1000,
/**
* ヘッダーの高さ
* style.scss の HEADER-HEIGHT と同じ高さを指定する
* @type {Number} 単位: px
*/
HEADER_HEIGHT: 50,
}
/**
* スクロールしたら呼び出される
* @param {Number} scrolled スクロール時のページ上部からの高さ
* @param {Number} previousScroll 前回の scrolled 値
*/
function onScroll(scrolled, previousScroll) {
const hd = document.querySelector('header');
// スクロール量がヘッダーの高さ未満のとき: ヘッダーは画面固定しない
if (scrolled <= CONSTS.HEADER_HEIGHT) {
if (hd.style.position !== 'absolute') hd.style.position = 'absolute';
if (hd.style.top !== '0') hd.style.top = '0';
}
// 下にスクロールしたとき: ヘッダーを非表示にする
else if (scrolled > previousScroll) {
if (hd.classList.contains('show')) hd.classList.remove('show');
if (!hd.classList.contains('hide')) hd.classList.add('hide');
}
// 上にバックスクロールしたとき: ヘッダーを表示する
else {
// 要素に付与されたスタイルはリセット
hd.style.top = '';
hd.style.position = '';
if (hd.classList.contains('hide')) hd.classList.remove('hide');
if (!hd.classList.contains('show')) hd.classList.add('show');
}
}
// DOM の読み込みが完了したら読み込まれる
document.addEventListener('DOMContentLoaded', () => {
// スクロール時に onScroll 関数を実行する
let previousScroll = 0;
let scrolled = 0;
window.addEventListener("scroll", async () => {
previousScroll = scrolled;
scrolled = window.pageYOffset
onScroll(scrolled, previousScroll);
});
});
注意点
CSS と JS で共通の値を設定すべきところがあります. しかし、このテンプレートの CSS は SCSS をコンバートしたものなので、その値を設定するときは SCSS を編集して再びコンバートしてください.
設定すべきところ:
- JS の HEADER_ANIMATION_DURATION と SCSS の $HEADER-ANIMATION-DURATION
- JS の HEADER_HEIGHT と SCSS の $HEADER-HEIGHT
また、コンテンツを作成するとき、header 要素の position が absolute や fixed になることに注意して下さい. コンテンツが header 要素の下にいったり、後ろにいったりします. 適宜調整が必要です
Discussion