アプリシェル(サイドバー+ヘッダー)

管理画面の定番構成。左サイドバー・上ヘッダー・メインを CSS Grid の grid-template-areas で組み、ボタンでサイドバーを畳んで表示領域を広げられる。

#css#grid#layout#dashboard

ライブデモ

コード

HTML
<!-- アプリシェル:サイドバー+ヘッダーを CSS Grid の grid-template-areas で構成 -->
<div class="ash" id="ashRoot">
  <aside class="ash__sidebar">
    <div class="ash__brand">
      <span class="ash__brand-icon">◆</span>
      <span class="ash__brand-text">Nimbus</span>
    </div>
    <nav class="ash__nav">
      <a class="is-active" href="#">
        <span class="ash__navicon">📊</span><span class="ash__navtext">ダッシュボード</span>
      </a>
      <a href="#">
        <span class="ash__navicon">📁</span><span class="ash__navtext">プロジェクト</span>
      </a>
      <a href="#">
        <span class="ash__navicon">👥</span><span class="ash__navtext">チーム</span>
      </a>
      <a href="#">
        <span class="ash__navicon">💳</span><span class="ash__navtext">請求</span>
      </a>
      <a href="#">
        <span class="ash__navicon">⚙️</span><span class="ash__navtext">設定</span>
      </a>
    </nav>
  </aside>

  <header class="ash__header">
    <button class="ash__toggle" id="ashToggle" type="button" aria-label="サイドバーの折りたたみ切替" aria-expanded="true">
      <span></span><span></span><span></span>
    </button>
    <span class="ash__title">ダッシュボード</span>
    <span class="ash__user">田中 ◉</span>
  </header>

  <main class="ash__main">
    <div class="ash__kpis">
      <div class="ash-kpi"><span>今月の売上</span><b>¥1.24M</b><i class="up">+12%</i></div>
      <div class="ash-kpi"><span>新規契約</span><b>48</b><i class="up">+6%</i></div>
      <div class="ash-kpi"><span>解約率</span><b>1.8%</b><i class="down">-0.3%</i></div>
    </div>
    <div class="ash__panel">
      <p class="ash__panel-h">最近のアクティビティ</p>
      <ul class="ash__feed">
        <li><span class="dot dot--b"></span>佐藤さんが「請求API」タスクを完了しました</li>
        <li><span class="dot dot--g"></span>新規プロジェクト「Q3刷新」が作成されました</li>
        <li><span class="dot"></span>山田さんがレポートにコメントを追加しました</li>
      </ul>
    </div>
  </main>
</div>
CSS
/* 全体:明るいSaaSダッシュボード風。CSS Grid の grid-template-areas でシェルを構成 */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  font-family: "Hiragino Sans", system-ui, sans-serif;
  background: #eef1f7;
  color: #1c2333;
  min-height: 100vh;
  display: block; /* ビルダーの flex 中央寄せを解除し、フルブリードのシェルを表示 */
}

/* ルート:width:100% が無いと親の flex 中央寄せでグリッドが潰れるため必須 */
.ash {
  width: 100%;
  min-height: 100vh;
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 56px 1fr;
  grid-template-areas:
    "side head"
    "side main";
  transition: grid-template-columns .22s ease;
}

/* サイドバー */
.ash__sidebar {
  grid-area: side;
  background: #14192b;
  color: #cbd3e6;
  padding: 16px 14px;
  display: flex; flex-direction: column; gap: 18px;
  overflow: hidden;
}
.ash__brand { display: flex; align-items: center; gap: 8px; padding: 0 6px; white-space: nowrap; }
.ash__brand-icon { color: #7dd3fc; font-size: 18px; }
.ash__brand-text { font-weight: 800; letter-spacing: .04em; color: #f1f5f9; }

.ash__nav { display: flex; flex-direction: column; gap: 4px; }
.ash__nav a {
  display: flex; align-items: center; gap: 10px; white-space: nowrap;
  color: #aab3ca; text-decoration: none; font-size: 13px; font-weight: 600;
  padding: 9px 10px; border-radius: 9px; transition: background .18s, color .18s;
}
.ash__nav a:hover { background: #1d2440; color: #e2e8f0; }
.ash__nav a.is-active { background: #223056; color: #7dd3fc; }
.ash__navicon { font-size: 15px; width: 18px; text-align: center; flex-shrink: 0; }

/* ヘッダー */
.ash__header {
  grid-area: head;
  display: flex; align-items: center; gap: 12px;
  padding: 0 18px; background: #ffffff; border-bottom: 1px solid #e2e8f0;
}
.ash__toggle {
  width: 30px; height: 30px; border-radius: 8px; border: 1px solid #dde3ee;
  background: #fff; cursor: pointer; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 4px; flex-shrink: 0;
}
.ash__toggle span { width: 14px; height: 2px; background: #47506b; border-radius: 2px; }
.ash__toggle:hover { background: #f3f5f9; }
.ash__title { font-weight: 800; font-size: 14px; color: #1c2333; }
.ash__user { margin-left: auto; font-size: 13px; color: #5b6478; font-weight: 600; }

/* メイン */
.ash__main { grid-area: main; padding: 20px 22px; overflow: auto; }
.ash__kpis { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; }
.ash-kpi {
  flex: 1 1 140px; background: #fff; border: 1px solid #e6eaf2; border-radius: 12px;
  padding: 12px 14px; display: flex; flex-direction: column; gap: 4px;
}
.ash-kpi span { font-size: 11px; color: #7c869c; font-weight: 700; letter-spacing: .03em; }
.ash-kpi b { font-size: 20px; color: #161c2c; }
.ash-kpi i { font-size: 11px; font-weight: 700; font-style: normal; width: fit-content; padding: 1px 6px; border-radius: 20px; }
.ash-kpi i.up { color: #059669; background: #d1fae5; }
.ash-kpi i.down { color: #dc2626; background: #fee2e2; }

.ash__panel { background: #fff; border: 1px solid #e6eaf2; border-radius: 12px; padding: 16px; }
.ash__panel-h { font-size: 12px; font-weight: 800; color: #47506b; margin-bottom: 10px; }
.ash__feed { list-style: none; display: flex; flex-direction: column; gap: 9px; }
.ash__feed li { display: flex; align-items: center; gap: 9px; font-size: 13px; color: #333c50; }
.dot { width: 7px; height: 7px; border-radius: 50%; background: #94a3b8; flex-shrink: 0; }
.dot--b { background: #38bdf8; }
.dot--g { background: #34d399; }

/* 折りたたみ:ボタンでアイコンレールに縮小(is-collapsed は JS が root に付け外し) */
.ash.is-collapsed { grid-template-columns: 60px 1fr; }
.ash.is-collapsed .ash__brand-text,
.ash.is-collapsed .ash__navtext { display: none; }
.ash.is-collapsed .ash__nav a { justify-content: center; }
.ash.is-collapsed .ash__brand { justify-content: center; }

/* 狭幅では初期状態からアイコンレールにし、トグルでさらに完全に隠せる */
@media (max-width: 640px) {
  .ash { grid-template-columns: 60px 1fr; }
  .ash__brand-text, .ash__navtext { display: none; }
  .ash__nav a { justify-content: center; }
  .ash__brand { justify-content: center; }
  .ash.is-collapsed { grid-template-columns: 0px 1fr; }
  .ash.is-collapsed .ash__sidebar { padding: 0; overflow: hidden; }
}

@media (prefers-reduced-motion: reduce) {
  .ash { transition: none; }
  .ash__nav a { transition: none; }
}
JavaScript
// サイドバー折りたたみトグル+ナビのアクティブ切替(null安全)
(() => {
  const root = document.getElementById('ashRoot');
  const toggle = document.getElementById('ashToggle');
  if (!root || !toggle) return;

  toggle.addEventListener('click', () => {
    const collapsed = root.classList.toggle('is-collapsed');
    toggle.setAttribute('aria-expanded', String(!collapsed));
  });

  const links = root.querySelectorAll('.ash__nav a');
  links.forEach((link) => {
    link.addEventListener('click', (e) => {
      e.preventDefault();
      links.forEach((l) => l.classList.remove('is-active'));
      link.classList.add('is-active');
    });
  });
})();

🤖 AIエージェント用プロンプト

このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「アプリシェル(サイドバー+ヘッダー)」の効果を追加してください。

# 追加してほしい効果
アプリシェル(サイドバー+ヘッダー)(レイアウト & グリッド)
管理画面の定番構成。左サイドバー・上ヘッダー・メインを CSS Grid の grid-template-areas で組み、ボタンでサイドバーを畳んで表示領域を広げられる。

# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】

# 参考実装(この見た目・挙動を再現してください)
【HTML】
<!-- アプリシェル:サイドバー+ヘッダーを CSS Grid の grid-template-areas で構成 -->
<div class="ash" id="ashRoot">
  <aside class="ash__sidebar">
    <div class="ash__brand">
      <span class="ash__brand-icon">◆</span>
      <span class="ash__brand-text">Nimbus</span>
    </div>
    <nav class="ash__nav">
      <a class="is-active" href="#">
        <span class="ash__navicon">📊</span><span class="ash__navtext">ダッシュボード</span>
      </a>
      <a href="#">
        <span class="ash__navicon">📁</span><span class="ash__navtext">プロジェクト</span>
      </a>
      <a href="#">
        <span class="ash__navicon">👥</span><span class="ash__navtext">チーム</span>
      </a>
      <a href="#">
        <span class="ash__navicon">💳</span><span class="ash__navtext">請求</span>
      </a>
      <a href="#">
        <span class="ash__navicon">⚙️</span><span class="ash__navtext">設定</span>
      </a>
    </nav>
  </aside>

  <header class="ash__header">
    <button class="ash__toggle" id="ashToggle" type="button" aria-label="サイドバーの折りたたみ切替" aria-expanded="true">
      <span></span><span></span><span></span>
    </button>
    <span class="ash__title">ダッシュボード</span>
    <span class="ash__user">田中 ◉</span>
  </header>

  <main class="ash__main">
    <div class="ash__kpis">
      <div class="ash-kpi"><span>今月の売上</span><b>¥1.24M</b><i class="up">+12%</i></div>
      <div class="ash-kpi"><span>新規契約</span><b>48</b><i class="up">+6%</i></div>
      <div class="ash-kpi"><span>解約率</span><b>1.8%</b><i class="down">-0.3%</i></div>
    </div>
    <div class="ash__panel">
      <p class="ash__panel-h">最近のアクティビティ</p>
      <ul class="ash__feed">
        <li><span class="dot dot--b"></span>佐藤さんが「請求API」タスクを完了しました</li>
        <li><span class="dot dot--g"></span>新規プロジェクト「Q3刷新」が作成されました</li>
        <li><span class="dot"></span>山田さんがレポートにコメントを追加しました</li>
      </ul>
    </div>
  </main>
</div>

【CSS】
/* 全体:明るいSaaSダッシュボード風。CSS Grid の grid-template-areas でシェルを構成 */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  font-family: "Hiragino Sans", system-ui, sans-serif;
  background: #eef1f7;
  color: #1c2333;
  min-height: 100vh;
  display: block; /* ビルダーの flex 中央寄せを解除し、フルブリードのシェルを表示 */
}

/* ルート:width:100% が無いと親の flex 中央寄せでグリッドが潰れるため必須 */
.ash {
  width: 100%;
  min-height: 100vh;
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 56px 1fr;
  grid-template-areas:
    "side head"
    "side main";
  transition: grid-template-columns .22s ease;
}

/* サイドバー */
.ash__sidebar {
  grid-area: side;
  background: #14192b;
  color: #cbd3e6;
  padding: 16px 14px;
  display: flex; flex-direction: column; gap: 18px;
  overflow: hidden;
}
.ash__brand { display: flex; align-items: center; gap: 8px; padding: 0 6px; white-space: nowrap; }
.ash__brand-icon { color: #7dd3fc; font-size: 18px; }
.ash__brand-text { font-weight: 800; letter-spacing: .04em; color: #f1f5f9; }

.ash__nav { display: flex; flex-direction: column; gap: 4px; }
.ash__nav a {
  display: flex; align-items: center; gap: 10px; white-space: nowrap;
  color: #aab3ca; text-decoration: none; font-size: 13px; font-weight: 600;
  padding: 9px 10px; border-radius: 9px; transition: background .18s, color .18s;
}
.ash__nav a:hover { background: #1d2440; color: #e2e8f0; }
.ash__nav a.is-active { background: #223056; color: #7dd3fc; }
.ash__navicon { font-size: 15px; width: 18px; text-align: center; flex-shrink: 0; }

/* ヘッダー */
.ash__header {
  grid-area: head;
  display: flex; align-items: center; gap: 12px;
  padding: 0 18px; background: #ffffff; border-bottom: 1px solid #e2e8f0;
}
.ash__toggle {
  width: 30px; height: 30px; border-radius: 8px; border: 1px solid #dde3ee;
  background: #fff; cursor: pointer; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 4px; flex-shrink: 0;
}
.ash__toggle span { width: 14px; height: 2px; background: #47506b; border-radius: 2px; }
.ash__toggle:hover { background: #f3f5f9; }
.ash__title { font-weight: 800; font-size: 14px; color: #1c2333; }
.ash__user { margin-left: auto; font-size: 13px; color: #5b6478; font-weight: 600; }

/* メイン */
.ash__main { grid-area: main; padding: 20px 22px; overflow: auto; }
.ash__kpis { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; }
.ash-kpi {
  flex: 1 1 140px; background: #fff; border: 1px solid #e6eaf2; border-radius: 12px;
  padding: 12px 14px; display: flex; flex-direction: column; gap: 4px;
}
.ash-kpi span { font-size: 11px; color: #7c869c; font-weight: 700; letter-spacing: .03em; }
.ash-kpi b { font-size: 20px; color: #161c2c; }
.ash-kpi i { font-size: 11px; font-weight: 700; font-style: normal; width: fit-content; padding: 1px 6px; border-radius: 20px; }
.ash-kpi i.up { color: #059669; background: #d1fae5; }
.ash-kpi i.down { color: #dc2626; background: #fee2e2; }

.ash__panel { background: #fff; border: 1px solid #e6eaf2; border-radius: 12px; padding: 16px; }
.ash__panel-h { font-size: 12px; font-weight: 800; color: #47506b; margin-bottom: 10px; }
.ash__feed { list-style: none; display: flex; flex-direction: column; gap: 9px; }
.ash__feed li { display: flex; align-items: center; gap: 9px; font-size: 13px; color: #333c50; }
.dot { width: 7px; height: 7px; border-radius: 50%; background: #94a3b8; flex-shrink: 0; }
.dot--b { background: #38bdf8; }
.dot--g { background: #34d399; }

/* 折りたたみ:ボタンでアイコンレールに縮小(is-collapsed は JS が root に付け外し) */
.ash.is-collapsed { grid-template-columns: 60px 1fr; }
.ash.is-collapsed .ash__brand-text,
.ash.is-collapsed .ash__navtext { display: none; }
.ash.is-collapsed .ash__nav a { justify-content: center; }
.ash.is-collapsed .ash__brand { justify-content: center; }

/* 狭幅では初期状態からアイコンレールにし、トグルでさらに完全に隠せる */
@media (max-width: 640px) {
  .ash { grid-template-columns: 60px 1fr; }
  .ash__brand-text, .ash__navtext { display: none; }
  .ash__nav a { justify-content: center; }
  .ash__brand { justify-content: center; }
  .ash.is-collapsed { grid-template-columns: 0px 1fr; }
  .ash.is-collapsed .ash__sidebar { padding: 0; overflow: hidden; }
}

@media (prefers-reduced-motion: reduce) {
  .ash { transition: none; }
  .ash__nav a { transition: none; }
}

【JavaScript】
// サイドバー折りたたみトグル+ナビのアクティブ切替(null安全)
(() => {
  const root = document.getElementById('ashRoot');
  const toggle = document.getElementById('ashToggle');
  if (!root || !toggle) return;

  toggle.addEventListener('click', () => {
    const collapsed = root.classList.toggle('is-collapsed');
    toggle.setAttribute('aria-expanded', String(!collapsed));
  });

  const links = root.querySelectorAll('.ash__nav a');
  links.forEach((link) => {
    link.addEventListener('click', (e) => {
      e.preventDefault();
      links.forEach((l) => l.classList.remove('is-active'));
      link.classList.add('is-active');
    });
  });
})();

# 外部ライブラリ
なし(追加ライブラリ不要)

# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。