スティッキーサイドバー Sticky Sidebar

スクロールしても固定表示されるサイドバー。ナビや補足情報に使用。

使用場面: ドキュメントの目次やフィルターパネルをスクロール時も表示し続ける 採用例: MDN Docs, Tailwind CSS Docs

ライブデモ

CSS Gridで作る最新レイアウト

CSS Gridは2次元レイアウトを可能にするCSSの機能です。行と列を同時に制御できるため、複雑なレイアウトも直感的に構築できます。grid-template-areasを使えば、視覚的にレイアウトを定義することも可能です。レスポンシブ対応もメディアクエリとの組み合わせで柔軟に対応できます。

Flexboxとの使い分け

Flexboxは1次元(行または列)のレイアウトに最適です。ナビゲーションバーやカードの横並びなど、一方向の配置にはFlexboxを選びましょう。一方、ページ全体の骨格やダッシュボードのようなグリッド配置にはCSS Gridが向いています。両者を組み合わせることで、あらゆるレイアウトに対応できます。

レスポンシブデザインの基礎

モバイルファーストのアプローチでは、まずスマホ向けのスタイルを書き、min-widthのメディアクエリでデスクトップ向けに拡張します。ブレークポイントはコンテンツに合わせて設定し、デバイスの画面サイズに依存しないようにしましょう。clamp()関数を使えば、フォントサイズや余白をビューポート幅に連動させることもできます。

コンポーネント設計のベストプラクティス

再利用可能なコンポーネントを設計する際は、単一責任の原則を意識しましょう。1つのコンポーネントは1つの役割に集中させ、プロパティ(props/変数)で外観や振る舞いをカスタマイズ可能にします。BEM命名規則やCSS Modulesを使ってスタイルの衝突を防ぐことも重要です。

パフォーマンス最適化ガイド

Webパフォーマンスの改善にはCore Web Vitalsの3指標(LCP, FID, CLS)を把握することが重要です。画像の遅延読み込み、CSSの最適化、JavaScriptの分割読み込みなど、具体的な施策を優先度順に実施しましょう。Lighthouseを定期的に実行してスコアを監視することをお勧めします。

アクセシビリティを考慮した開発

WAI-ARIA属性を適切に使用し、スクリーンリーダーでも情報が正確に伝わるようにします。キーボード操作のサポート、十分なカラーコントラスト、フォーカスインジケーターの表示など、基本的なアクセシビリティ要件を確認しましょう。自動テストツールに加え、実際の支援技術での検証も重要です。

ソースコード

<div class="demo-sticky-wrap" style="display:flex;gap:20px;max-height:500px;overflow-y:auto;border:1px solid #e5e7eb;border-radius:10px;"><main style="flex:1;padding:20px;min-width:0;"><article style="margin-bottom:24px;padding-bottom:24px;border-bottom:1px solid #e5e7eb;"><h3 style="font-size:15px;font-weight:700;color:var(--ui-text,#333);margin:0 0 8px;">CSS Gridで作る最新レイアウト</h3><p style="font-size:13px;color:var(--ui-text-sub,#555);line-height:1.8;margin:0;">CSS Gridは2次元レイアウトを可能にするCSSの機能です。行と列を同時に制御できるため、複雑なレイアウトも直感的に構築できます。grid-template-areasを使えば、視覚的にレイアウトを定義することも可能です。レスポンシブ対応もメディアクエリとの組み合わせで柔軟に対応できます。</p></article><article style="margin-bottom:24px;padding-bottom:24px;border-bottom:1px solid #e5e7eb;"><h3 style="font-size:15px;font-weight:700;color:var(--ui-text,#333);margin:0 0 8px;">Flexboxとの使い分け</h3><p style="font-size:13px;color:var(--ui-text-sub,#555);line-height:1.8;margin:0;">Flexboxは1次元(行または列)のレイアウトに最適です。ナビゲーションバーやカードの横並びなど、一方向の配置にはFlexboxを選びましょう。一方、ページ全体の骨格やダッシュボードのようなグリッド配置にはCSS Gridが向いています。両者を組み合わせることで、あらゆるレイアウトに対応できます。</p></article><article style="margin-bottom:24px;padding-bottom:24px;border-bottom:1px solid #e5e7eb;"><h3 style="font-size:15px;font-weight:700;color:var(--ui-text,#333);margin:0 0 8px;">レスポンシブデザインの基礎</h3><p style="font-size:13px;color:var(--ui-text-sub,#555);line-height:1.8;margin:0;">モバイルファーストのアプローチでは、まずスマホ向けのスタイルを書き、min-widthのメディアクエリでデスクトップ向けに拡張します。ブレークポイントはコンテンツに合わせて設定し、デバイスの画面サイズに依存しないようにしましょう。clamp()関数を使えば、フォントサイズや余白をビューポート幅に連動させることもできます。</p></article><article style="margin-bottom:24px;padding-bottom:24px;border-bottom:1px solid #e5e7eb;"><h3 style="font-size:15px;font-weight:700;color:var(--ui-text,#333);margin:0 0 8px;">コンポーネント設計のベストプラクティス</h3><p style="font-size:13px;color:var(--ui-text-sub,#555);line-height:1.8;margin:0;">再利用可能なコンポーネントを設計する際は、単一責任の原則を意識しましょう。1つのコンポーネントは1つの役割に集中させ、プロパティ(props/変数)で外観や振る舞いをカスタマイズ可能にします。BEM命名規則やCSS Modulesを使ってスタイルの衝突を防ぐことも重要です。</p></article><article style="margin-bottom:24px;padding-bottom:24px;border-bottom:1px solid #e5e7eb;"><h3 style="font-size:15px;font-weight:700;color:var(--ui-text,#333);margin:0 0 8px;">パフォーマンス最適化ガイド</h3><p style="font-size:13px;color:var(--ui-text-sub,#555);line-height:1.8;margin:0;">Webパフォーマンスの改善にはCore Web Vitalsの3指標(LCP, FID, CLS)を把握することが重要です。画像の遅延読み込み、CSSの最適化、JavaScriptの分割読み込みなど、具体的な施策を優先度順に実施しましょう。Lighthouseを定期的に実行してスコアを監視することをお勧めします。</p></article><article style="margin-bottom:24px;padding-bottom:24px;"><h3 style="font-size:15px;font-weight:700;color:var(--ui-text,#333);margin:0 0 8px;">アクセシビリティを考慮した開発</h3><p style="font-size:13px;color:var(--ui-text-sub,#555);line-height:1.8;margin:0;">WAI-ARIA属性を適切に使用し、スクリーンリーダーでも情報が正確に伝わるようにします。キーボード操作のサポート、十分なカラーコントラスト、フォーカスインジケーターの表示など、基本的なアクセシビリティ要件を確認しましょう。自動テストツールに加え、実際の支援技術での検証も重要です。</p></article></main><aside class="demo-sticky-aside" style="width:200px;flex-shrink:0;position:sticky;top:0;align-self:flex-start;border-left:1px solid #e5e7eb;"><div style="padding:16px;border-bottom:1px solid #e5e7eb;text-align:center;"><div style="width:48px;height:48px;border-radius:50%;background:var(--ui-primary);margin:0 auto 8px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:700;font-size:18px;">T</div><div style="font-size:13px;font-weight:700;color:var(--ui-text,#333);">Taro Yamada</div><div style="font-size:11px;color:var(--ui-text-muted,#999);">フロントエンドエンジニア</div></div><div style="padding:12px 16px;"><div style="font-size:11px;font-weight:700;color:var(--ui-text-muted,#999);text-transform:uppercase;margin-bottom:8px;">人気の記事</div><a href="#" onclick="return false" style="display:block;font-size:12px;color:var(--ui-primary);text-decoration:none;padding:4px 0;border-bottom:1px solid #f0f0f0;">CSS Gridの基礎</a><a href="#" onclick="return false" style="display:block;font-size:12px;color:var(--ui-primary);text-decoration:none;padding:4px 0;border-bottom:1px solid #f0f0f0;">Flexbox完全ガイド</a><a href="#" onclick="return false" style="display:block;font-size:12px;color:var(--ui-primary);text-decoration:none;padding:4px 0;">変数設計パターン</a></div><div style="padding:12px 16px;border-top:1px solid #e5e7eb;"><div style="font-size:11px;font-weight:700;color:var(--ui-text-muted,#999);text-transform:uppercase;margin-bottom:8px;">タグ</div><div style="display:flex;flex-wrap:wrap;gap:4px;"><span style="font-size:11px;padding:2px 8px;border-radius:10px;background:var(--ui-primary-light,rgba(37,99,235,0.1));color:var(--ui-primary);">CSS</span><span style="font-size:11px;padding:2px 8px;border-radius:10px;background:var(--ui-primary-light,rgba(37,99,235,0.1));color:var(--ui-primary);">Layout</span><span style="font-size:11px;padding:2px 8px;border-radius:10px;background:var(--ui-primary-light,rgba(37,99,235,0.1));color:var(--ui-primary);">React</span><span style="font-size:11px;padding:2px 8px;border-radius:10px;background:var(--ui-primary-light,rgba(37,99,235,0.1));color:var(--ui-primary);">A11y</span></div></div></aside></div>
<button class="demo-sticky-fab" id="demo-sticky-fab" aria-label="サイドバーを開く"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></button>
.demo-sticky-wrap { min-height: 450px;
  display: flex; gap: 20px; max-height: 280px; overflow-y: auto;
  position: relative;
}
.demo-sticky-main { flex: 1; }
.demo-sticky-section {
  padding: 16px 0; border-bottom: 1px solid #f3f4f6;
  min-height: 100px;
}
.demo-sticky-section:last-child { border-bottom: none; }
.demo-sticky-heading {
  margin: 0 0 8px; font-size: 16px; font-weight: 700;
  color: var(--ui-primary);
}
.demo-sticky-section p {
  margin: 0; font-size: 13px; color: #555; line-height: 1.7;
}
.demo-sticky-sidebar {
  flex: 0 0 140px; position: sticky; top: 0; align-self: flex-start;
}
.demo-sticky-toc {
  padding: 14px; border-radius: 10px;
  background: color-mix(in srgb, var(--ui-primary) 4%, #fff);
  border: 1px solid color-mix(in srgb, var(--ui-primary) 12%, transparent);
}
.demo-sticky-toc-title {
  margin: 0 0 10px; font-size: 12px; font-weight: 700;
  color: var(--ui-primary); text-transform: uppercase;
  letter-spacing: 0.5px;
}
.demo-sticky-toc-link {
  display: block; padding: 5px 8px; font-size: 12px;
  text-decoration: none; color: #777; border-radius: 4px;
  border-left: 2px solid transparent; margin-left: -2px;
  transition: all 0.2s;
}
.demo-sticky-toc-link:hover { color: #444; }
.demo-sticky-toc-link.active {
  color: var(--ui-primary); font-weight: 600;
  border-left-color: var(--ui-primary);
  background: color-mix(in srgb, var(--ui-primary) 8%, #fff);
}


}
[data-ui-theme="light"] .demo-sticky-aside.is-open { background: #ffffff !important; }
[data-ui-theme="dark"] .demo-sticky-aside.is-open { background: #18181f !important; }
.demo-sticky-fab svg { pointer-events: none; }
.demo-sticky-aside { background: var(--ui-surface, #fff); }
@media (max-width: 767px) {
  .demo-sticky-wrap {
    flex-direction: column !important;
    max-height: 450px !important;
    overflow-y: auto !important;
    position: relative !important;
  }
  .demo-sticky-aside {
    display: none !important;
    position: absolute !important;
    bottom: 56px; left: 8px;
    width: 240px;
    z-index: 50;
    border-radius: 12px;
    border: 1px solid #e5e7eb;
    box-shadow: 0 8px 24px rgba(0,0,0,0.15);
    max-height: 280px;
    overflow-y: auto;
    border-left: none !important;
  }
  [data-ui-theme="light"] .demo-sticky-aside.is-open { display: block !important; background: #ffffff !important; }
  [data-ui-theme="dark"] .demo-sticky-aside.is-open { display: block !important; background: #1f1f28 !important; }
  .demo-sticky-fab {
    display: flex !important;
    position: absolute !important;
    bottom: 8px; right: 8px;
    z-index: 51;
    width: 44px; height: 44px;
    border-radius: 50%; border: none;
    background: var(--ui-primary); color: #fff;
    cursor: pointer;
    align-items: center; justify-content: center;
    box-shadow: 0 4px 12px rgba(0,0,0,0.2);
  }
  .demo-sticky-main { max-height: none !important; overflow: visible !important; padding: 16px !important; }
}
@media (min-width: 768px) {
  .demo-sticky-fab { display: none !important; }
}
(function(){
  var fab = document.getElementById('demo-sticky-fab');
  var aside = document.querySelector('.demo-sticky-aside');
  var openIcon = '<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>';
  var closeIcon = '<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>';
  if(!fab || !aside) return;
  var isOpen = false;
  fab.addEventListener('click', function(e){
    e.stopPropagation();
    isOpen = !isOpen;
    if(isOpen) aside.classList.add('is-open');
    else aside.classList.remove('is-open');
    fab.innerHTML = isOpen ? closeIcon : openIcon;
  });
  document.addEventListener('click', function(e){
    if(!isOpen) return;
    if(aside.contains(e.target)) return;
    isOpen = false;
    aside.classList.remove('is-open');
    fab.innerHTML = openIcon;
  });
})();

AIプロンプト

Basic
スティッキーサイドバーをHTML/CSSで作ってください。メインコンテンツをスクロールしてもサイドバーが固定表示されます。
Custom
以下の仕様でスティッキーサイドバーを実装してください。
- position: stickyでサイドバーを固定
- サイドバーに目次(TOC)を表示
- スクロールスパイで現在セクションをハイライト
- プライマリカラー: #2563eb
- サイドバーの高さがビューポートを超える場合の対応
- レスポンシブ(モバイルではサイドバーを上部に移動)
Advanced
アクセシビリティ対応のスティッキーサイドバーを実装してください。
- aside要素とnav要素の適切な使い分け
- aria-label でサイドバーの役割を明示
- スクロールスパイのaria-current対応
- キーボードナビゲーション
- prefers-reduced-motion でスムーズスクロール無効化
- sticky要素のスクロール領域制限(サイドバーがメインより長い場合)
- IntersectionObserver でパフォーマンス最適化
- print用スタイル(stickyを解除して通常配置)