はじめに
「スティッキーヘッダーの実装は分かるけど、動きのあるものが作れない」という方も多いのではないでしょうか。
今回は、コピペするだけですぐに使えるスクロールヘッダーメニューを5つご紹介します。
すべてモダンな書き方で、スムーズなアニメーションとユーザビリティを実現しています。
この記事を読み終える頃には、プロジェクトに最適なスクロールヘッダーを選んで実装できるようになりますので、ぜひ参考にしてみてください。
1. ベーシック – 下スクロールで隠れる
最もシンプルでよく使われるパターンです。
下にスクロールするとヘッダーが隠れ、上にスクロールすると再び表示されます。
See the Pen Untitled by ryoma (@hwjgdjpk-the-decoder) on CodePen.
特徴
- 下スクロールで隠れる
- 上スクロールで現れる
- スムーズなトランジション
HTML
<header id="header" class="header">
<div class="header__inner">
<div class="header__logo">
<a href="/">LOGO</a>
</div>
<nav class="header__nav">
<ul class="header__list">
<li><a href="#about">About</a></li>
<li><a href="#service">Service</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</div>
</header>
<!-- スクロール確認用のコンテンツ -->
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #f0f0f0 0%, #e0e0e0 100%);">
<h2 style="font-size: 2rem; color: #333;">スクロールしてヘッダーの動きを確認</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #e0e0e0 0%, #d0d0d0 100%);">
<h2 style="font-size: 2rem; color: #333;">下スクロールでヘッダーが隠れます</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #d0d0d0 0%, #c0c0c0 100%);">
<h2 style="font-size: 2rem; color: #333;">上スクロールでヘッダーが現れます</h2>
</div>
CSS
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #fff;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
transition: transform 0.3s ease;
z-index: 1000;
}
.header__inner {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.header__logo a {
font-size: 24px;
font-weight: bold;
color: #333;
text-decoration: none;
}
.header__list {
display: flex;
gap: 30px;
margin: 0;
padding: 0;
list-style: none;
}
.header__list a {
color: #333;
text-decoration: none;
transition: color 0.3s;
}
.header__list a:hover {
color: #4a90e2;
}
/* ヘッダーを隠すクラス */
.header--hidden {
transform: translateY(-100%);
}
JavaScript
let lastScrollTop = 0;
const header = document.getElementById('header');
const scrollThreshold = 100; // スクロール量の閾値
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
// 下スクロール時(現在位置が前回より下)
if (scrollTop > lastScrollTop && scrollTop > scrollThreshold) {
header.classList.add('header--hidden');
}
// 上スクロール時
else {
header.classList.remove('header--hidden');
}
lastScrollTop = scrollTop;
});
カスタマイズのポイント
transition
の時間を変更してアニメーション速度を調整scrollThreshold
を変更して反応するスクロール量を調整
2. フェードイン – 透明度変化
スクロール時に透明度を変化させながら表示/非表示を切り替えるパターンです。
See the Pen Untitled by ryoma (@hwjgdjpk-the-decoder) on CodePen.
特徴
- 透明度のアニメーション
- よりソフトな印象
- 背景のブラー効果付き
HTML
<header id="fade-header" class="fade-header">
<div class="fade-header__inner">
<div class="fade-header__logo">
<a href="/">BRAND</a>
</div>
<nav class="fade-header__nav">
<ul class="fade-header__menu">
<li><a href="#home">Home</a></li>
<li><a href="#works">Works</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</div>
</header>
<!-- スクロール確認用のコンテンツ -->
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #fff 0%, #f5f5f5 100%);">
<h2 style="font-size: 2rem; color: #333;">フェードイン効果を確認</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #f5f5f5 0%, #ebebeb 100%);">
<h2 style="font-size: 2rem; color: #333;">透明度が変化しながら消えます</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #ebebeb 0%, #e0e0e0 100%);">
<h2 style="font-size: 2rem; color: #333;">上スクロールでフェードイン</h2>
</div>
CSS
.fade-header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
box-shadow: 0 1px 20px rgba(0,0,0,0.05);
opacity: 1;
visibility: visible;
transition: opacity 0.4s ease, visibility 0.4s ease, transform 0.4s ease;
z-index: 1000;
}
.fade-header__inner {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
padding: 15px 20px;
}
.fade-header__logo a {
font-size: 22px;
font-weight: 700;
color: #222;
text-decoration: none;
letter-spacing: 1px;
}
.fade-header__menu {
display: flex;
gap: 35px;
margin: 0;
padding: 0;
list-style: none;
}
.fade-header__menu a {
position: relative;
color: #555;
font-size: 15px;
text-decoration: none;
transition: color 0.3s;
}
.fade-header__menu a::after {
content: '';
position: absolute;
bottom: -5px;
left: 0;
width: 0;
height: 2px;
background-color: #4a90e2;
transition: width 0.3s;
}
.fade-header__menu a:hover {
color: #4a90e2;
}
.fade-header__menu a:hover::after {
width: 100%;
}
/* ヘッダーを隠すクラス */
.fade-header--hidden {
opacity: 0;
visibility: hidden;
transform: translateY(-20px);
}
JavaScript
let lastScrollY = 0;
const fadeHeader = document.getElementById('fade-header');
const fadeThreshold = 150;
window.addEventListener('scroll', () => {
const currentScrollY = window.scrollY;
// 下スクロール時に非表示
if (currentScrollY > lastScrollY && currentScrollY > fadeThreshold) {
fadeHeader.classList.add('fade-header--hidden');
}
// 上スクロール時に表示
else if (currentScrollY < lastScrollY) {
fadeHeader.classList.remove('fade-header--hidden');
}
lastScrollY = currentScrollY;
});
カスタマイズのポイント
backdrop-filter
のblur値を変更して背景のぼかし具合を調整opacity
の値を変更して透明度を調整
3. スティッキー変形 – スクロールで縮小
スクロールに応じてヘッダーのサイズが変化するパターンです。
See the Pen Untitled by ryoma (@hwjgdjpk-the-decoder) on CodePen.
特徴
- スクロール時にヘッダーが縮小
- ロゴサイズも連動して変化
- 常に表示され続ける
HTML
<header id="sticky-header" class="sticky-header">
<div class="sticky-header__container">
<div class="sticky-header__logo">
<img src="https://placehold.co/200x80?text=Logo" alt="Logo" class="sticky-header__logo-img">
</div>
<nav class="sticky-header__nav">
<ul class="sticky-header__list">
<li><a href="#home">Home</a></li>
<li><a href="#portfolio">Portfolio</a></li>
<li><a href="#services">Services</a></li>
<li><a href="#blog">Blog</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</div>
</header>
<!-- スクロール確認用のコンテンツ -->
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #fafafa 0%, #f0f0f0 100%);">
<h2 style="font-size: 2rem; color: #333;">スクロールでヘッダーが縮小します</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #f0f0f0 0%, #e5e5e5 100%);">
<h2 style="font-size: 2rem; color: #333;">ロゴサイズも連動して変化</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #e5e5e5 0%, #dadada 100%);">
<h2 style="font-size: 2rem; color: #333;">常に表示され続けます</h2>
</div>
CSS
.sticky-header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #fff;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
transition: all 0.3s ease;
z-index: 1000;
}
.sticky-header__container {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
padding: 25px 20px;
transition: padding 0.3s ease;
}
.sticky-header__logo-img {
height: 40px;
transition: height 0.3s ease;
}
.sticky-header__list {
display: flex;
gap: 40px;
margin: 0;
padding: 0;
list-style: none;
}
.sticky-header__list a {
color: #333;
font-size: 16px;
text-decoration: none;
transition: all 0.3s;
}
.sticky-header__list a:hover {
color: #4a90e2;
}
/* スクロール時のスタイル */
.sticky-header--scrolled {
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.sticky-header--scrolled .sticky-header__container {
padding: 15px 20px;
}
.sticky-header--scrolled .sticky-header__logo-img {
height: 30px;
}
.sticky-header--scrolled .sticky-header__list a {
font-size: 14px;
}
JavaScript
const stickyHeader = document.getElementById('sticky-header');
const scrollPoint = 100;
window.addEventListener('scroll', () => {
if (window.scrollY > scrollPoint) {
stickyHeader.classList.add('sticky-header--scrolled');
} else {
stickyHeader.classList.remove('sticky-header--scrolled');
}
});
カスタマイズのポイント
- パディングの値を変更してヘッダーの高さを調整
- ロゴのheightを変更してサイズ変化を調整
4. プログレスバー付き – 読了率表示
スクロール量に応じてプログレスバーが表示されるパターンです。
See the Pen Untitled by ryoma (@hwjgdjpk-the-decoder) on CodePen.
特徴
- ページの読了率を可視化
- ヘッダー下部にプログレスバー
- スクロールで隠れる機能付き
HTML
<header id="progress-header" class="progress-header">
<div class="progress-header__main">
<div class="progress-header__inner">
<div class="progress-header__logo">
<a href="/">SITE LOGO</a>
</div>
<nav class="progress-header__nav">
<ul class="progress-header__menu">
<li><a href="#intro">Intro</a></li>
<li><a href="#content">Content</a></li>
<li><a href="#gallery">Gallery</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</div>
</div>
<div class="progress-header__bar">
<div class="progress-header__fill" id="progress-fill"></div>
</div>
</header>
<!-- スクロール確認用のコンテンツ -->
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);">
<h2 style="font-size: 2rem; color: #333;">プログレスバーがスクロール量を表示</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #e9ecef 0%, #dee2e6 100%);">
<h2 style="font-size: 2rem; color: #333;">読了率が一目でわかります</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #dee2e6 0%, #ced4da 100%);">
<h2 style="font-size: 2rem; color: #333;">記事の進捗を可視化</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #ced4da 0%, #adb5bd 100%);">
<h2 style="font-size: 2rem; color: #333;">最後までスクロールで100%</h2>
</div>
CSS
.progress-header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
transform: translateY(0);
transition: transform 0.3s ease;
z-index: 1000;
}
.progress-header__main {
border-bottom: 1px solid #eee;
}
.progress-header__inner {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
padding: 18px 20px;
}
.progress-header__logo a {
font-size: 20px;
font-weight: bold;
color: #2c3e50;
text-decoration: none;
}
.progress-header__menu {
display: flex;
gap: 30px;
margin: 0;
padding: 0;
list-style: none;
}
.progress-header__menu a {
color: #555;
font-size: 15px;
text-decoration: none;
transition: color 0.3s;
}
.progress-header__menu a:hover {
color: #3498db;
}
/* プログレスバー */
.progress-header__bar {
position: relative;
width: 100%;
height: 3px;
background-color: #f0f0f0;
}
.progress-header__fill {
position: absolute;
top: 0;
left: 0;
height: 100%;
background: linear-gradient(90deg, #3498db, #2ecc71);
width: 0%;
transition: width 0.2s ease;
}
JavaScript
const progressFill = document.getElementById('progress-fill');
// スクロール進捗の計算と表示
function updateProgress() {
const winScroll = document.body.scrollTop || document.documentElement.scrollTop;
const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
const scrolled = (winScroll / height) * 100;
progressFill.style.width = scrolled + '%';
}
// スクロール時にプログレスバーを更新
window.addEventListener('scroll', () => {
updateProgress();
});
カスタマイズのポイント
- プログレスバーの高さを
height
で調整 - グラデーションの色を
background
で変更
5. インタラクティブ – スクロール速度検知
スクロール速度を検知して動作を変えるパターンです。
See the Pen 5. インタラクティブ – スクロール速度検知 by ryoma (@hwjgdjpk-the-decoder) on CodePen.
特徴
- 高速スクロール時は即座に隠れる
- ゆっくりスクロール時は表示維持
- スクロール停止で自動表示
HTML
<header id="smart-header" class="smart-header">
<div class="smart-header__wrapper">
<div class="smart-header__brand">
<h1 class="smart-header__title">Smart Header</h1>
</div>
<nav class="smart-header__navigation">
<ul class="smart-header__items">
<li><a href="#features">Features</a></li>
<li><a href="#pricing">Pricing</a></li>
<li><a href="#docs">Docs</a></li>
<li><a href="#support">Support</a></li>
</ul>
<button class="smart-header__cta">Get Started</button>
</nav>
</div>
</header>
<!-- スクロール確認用のコンテンツ -->
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #f8f9ff 0%, #e8eaff 100%);">
<h2 style="font-size: 2rem; color: #333;">スクロール速度を検知します</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #e8eaff 0%, #d8dbff 100%);">
<h2 style="font-size: 2rem; color: #333;">高速スクロールで即座に隠れる</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #d8dbff 0%, #c8ccff 100%);">
<h2 style="font-size: 2rem; color: #333;">ゆっくりスクロールなら表示維持</h2>
</div>
<div style="height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(180deg, #c8ccff 0%, #b8bdff 100%);">
<h2 style="font-size: 2rem; color: #333;">スクロール停止で自動表示</h2>
</div>
CSS
.smart-header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
transform: translateY(0);
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 1000;
}
.smart-header__wrapper {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
padding: 15px 20px;
}
.smart-header__title {
margin: 0;
color: #fff;
font-size: 24px;
font-weight: 700;
}
.smart-header__navigation {
display: flex;
align-items: center;
gap: 40px;
}
.smart-header__items {
display: flex;
gap: 30px;
margin: 0;
padding: 0;
list-style: none;
}
.smart-header__items a {
color: rgba(255, 255, 255, 0.9);
font-size: 15px;
text-decoration: none;
transition: color 0.3s;
}
.smart-header__items a:hover {
color: #fff;
}
.smart-header__cta {
padding: 8px 20px;
background-color: rgba(255, 255, 255, 0.2);
border: 2px solid #fff;
border-radius: 25px;
color: #fff;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
}
.smart-header__cta:hover {
background-color: #fff;
color: #667eea;
}
/* 状態クラス */
.smart-header--hidden {
transform: translateY(-100%);
}
.smart-header--mini {
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
}
.smart-header--mini .smart-header__wrapper {
padding: 10px 20px;
}
JavaScript
let lastScroll = 0;
let scrollSpeed = 0;
let scrollTimer = null;
const smartHeader = document.getElementById('smart-header');
const speedThreshold = 25; // スクロール速度の閾値
const positionThreshold = 100;
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
// スクロール速度を計算
scrollSpeed = Math.abs(currentScroll - lastScroll);
// 高速スクロール時の処理
if (scrollSpeed > speedThreshold && currentScroll > positionThreshold) {
// 下スクロール
if (currentScroll > lastScroll) {
smartHeader.classList.add('smart-header--hidden');
}
}
// スクロール位置による処理
if (currentScroll > positionThreshold) {
smartHeader.classList.add('smart-header--mini');
} else {
smartHeader.classList.remove('smart-header--mini');
}
// スクロール停止を検知
clearTimeout(scrollTimer);
scrollTimer = setTimeout(() => {
// スクロール停止時は表示
smartHeader.classList.remove('smart-header--hidden');
}, 150);
lastScroll = currentScroll;
});
カスタマイズのポイント
speedThreshold
でスクロール速度の感度を調整setTimeout
の時間で停止検知のタイミングを調整
まとめ
今回はスクロールで現れるヘッダーメニューを使った実装方法を5つご紹介しました。
どれもコピペするだけで使えるので、プロジェクトに合わせて選んでみてください。
特に「ベーシック」タイプは実装がシンプルで使いやすく、「プログレスバー付き」は読み物系のサイトに最適なので、迷った場合はこちらから試してみることをおすすめします。
このブログでは他にもモーダルウィンドウやアコーディオンメニューについて解説していますので、あわせて参考にしてみてください。