固定サイドバー
フロー
固定なのでフロー外
位置指定
- top / left / right で直接指定
- メインコンテンツ
→サイドバーの存在を知らないまま描画されるのでこのままだとサイドバーの下に一部隠れてしまう
→横に余白をつける必要がある - 固定ヘッダーがある場合、ヘッダーも フロー外 なので、サイドバーと重なる可能性がある
→サイドバーは固定ヘッダー分上に余白をつける必要がある
例:
rx.css
#sidebar {
top: 100px; /* ヘッダー高さ */
}
大きさ
-
min-hight:1000px;=最小の高さを 1000px にする という指定 - コンテンツが少なくても 縦方向の高さが必ず 1000px になる
- コンテンツが 1000px より多ければ、自動的にそれ以上に伸びる
スクロール
- サイドバーの高さを固定していない場合 → サイドバーはコンテンツに合わせて伸びる
- 例:
ex.css
#sidebar {
position: fixed;
top: 100px; /* ヘッダー分オフセット */
bottom: 0; /* 画面下まで広げる */
width: 200px;
overflow: auto; /* はみ出すとスクロール */
}
- 上下を指定 → 高さが自動で計算される&内容が多ければ内部にスクロールが出る
- このように高さを指定するとサイドバーは高さを400pxのままをキープ
→コンテンツがサイドバーの枠を超えると はみ出してしまう
→自動スクロールをつけるには高さを決めて overflow: auto を指定
例
Ex.css
height: 400px; /* 固定高さ */
overflow: auto; /* 内容がはみ出したらスクロール */
完成コード
ex.css
<style>
* {
box-sizing: border-box;
}
#side {
position: fixed;
top: 10px;
left: 0;
width: 240px;
height: 600px;
border: 3px solid teal;
background: #e0f7f7;
overflow: auto;
}
#main {
/* サイドバー幅 */
margin-left: 260px;
border: 3px solid red;
padding: 10px;
min-height: 1000px;
}
</style>
ex.ma
<div id="side">
<h3>サイドバー</h3>
</div>
<div id="main">
<h2>本文</h2>
<p>スクロール確認用コンテンツ...</p>
</div>
sticky&Flexによるサイドバー
フロー
- フロー内
- メインコンテンツと横並びできる
- 上方向にスクロールして top にぶつかると固定される
位置指定
- position: sticky は フロー内の要素が親コンテナを基準に動く
ex.ma
<body>
<div class="container"> ←親
<div id="sidebar"> ← sticky対象
</div>
<div id="main">
</div>
</div>
</body>
→サイドバーは .container を スクロールの範囲として認識
→サイドバーがスクロールで top:0 に張り付くのは container内だけ
→containerの終わり(下端)に達すると、それ以上スクロールしてもsidebarは それ以上下に移動しない
完成コード
ex.css
<style>
* {
box-sizing: border-box;
}
/* 親コンテナ:サイドバーとメインを横並び */
.container {
display: flex;
max-width: 1600px;
margin: 0 auto;
}
#side {
position: sticky;
top: 10px;
width: 240px;
height: 400px;
border: 3px solid teal;
background: #e0f7f7;
overflow: auto;
}
#main {
/* サイドバー幅 */
flex: 1;
border: 3px solid red;
margin-left: 50px;
min-height: 1000px;
}
</style>
ex.ma
<body>
<div class="container">
<div id="side">
<h3>サイドバー</h3>
<p>リンク1</p>
<p>リンク2</p>
<p>リンク3</p>
<p>リンク4</p>
<p>リンク5</p>
<p>リンク6</p>
<p>リンク7</p>
<p>リンク8</p>
<p>リンク9</p>
<p>リンク10</p>
</div>
<div id="main">
<h2>本文</h2>
<p>スクロール確認用コンテンツ…</p>
</div>
</div>
</body>
- 親コンテナにmainとサイドバー(どちらもブロック要素)を入れる
→flexを指定して子供たちを横並びに! -
flex:1;=flexboxコンテナ内の子要素に使う - 「残りの幅を自分の割合で分けてもらう」指定
- 子が1つなら 全部もらう
- 子が複数なら 比率で分け合う
- サイドバーの横幅を指定済みなのでmain = 残りのコンテナ幅を flex:1 で自動拡張
Gridでの2カラム比較
display:grid;- 親要素を「格子(グリッド)」として扱う
→子要素を 行(row)・列(column) に自由に配置できる - 横並びだけでなく縦方向の整列も簡単にできる
- flex は「一列・一行」に沿った配置が基本なのに対して、grid は 行と列の両方を意識できる
フロー
フロー内
位置指定
- Grid は 親の grid-template-columns で列幅を決めるので、子の width は基本不要
- Grid の場合は 列間の隙間は gap で管理する のが自然
大きさ
サイドバーは200px,mainは残り
完成コード
ex.css
<style>
* {
box-sizing: border-box;
}
/* 親コンテナ:サイドバーとメインを横並び */
.container {
display: grid;
grid-template-columns: 200px 1fr;
/* サイドバー固定 + main残り幅 */
max-width: 1200px;
margin: 0 auto;
gap: 10px;
/* 列の間の隙間 */
}
#side {
top: 10px;
height: 400px;
border: 3px solid teal;
background: #e0f7f7;
overflow: auto;
}
#main {
/* サイドバー幅 */
border: 3px solid red;
min-height: 1000px;
}
</style>
ex.ma
<div class="container">
<div id="side">
<h3>サイドバー</h3>
<p>リンク1</p>
<p>リンク2</p>
<p>リンク3</p>
<p>リンク4</p>
<p>リンク5</p>
<p>リンク6</p>
<p>リンク7</p>
<p>リンク8</p>
<p>リンク9</p>
<p>リンク10</p>
</div>
<div id="main">
<h2>本文</h2>
<p>Grid版の2カラムです。mainは残り幅を自動で占有します。</p>
<p style="height:800px;">スクロール確認用(長いコンテンツ)</p>
</div>
</div>