【コピペOK】スクロールで現れるヘッダーメニュー5選

#HTML & CSS / #JavaScript

はじめに

「スティッキーヘッダーの実装は分かるけど、動きのあるものが作れない」という方も多いのではないでしょうか。

今回は、コピペするだけですぐに使えるスクロールヘッダーメニューを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つご紹介しました。

どれもコピペするだけで使えるので、プロジェクトに合わせて選んでみてください。

特に「ベーシック」タイプは実装がシンプルで使いやすく、「プログレスバー付き」は読み物系のサイトに最適なので、迷った場合はこちらから試してみることをおすすめします。

このブログでは他にもモーダルウィンドウやアコーディオンメニューについて解説していますので、あわせて参考にしてみてください。

りょうま

りょうま

Frontend Developer

北海道・十勝を拠点にフリーランスのフロントエンドエンジニアとして活動。
React、TypeScript、Shopifyを使ったモダンなWebアプリケーション開発を得意としています。
ユーザー体験を重視したインターフェース設計・実装を行っています。