はじめに
CSSの scroll-padding-top と scroll-margin-top プロパティについて解説する。まず、これらのプロパティを理解する上で重要となる「スクロールコンテナ」と「スナップターゲット」について、簡単に説明する。
- スクロールコンテナ (Scroll Container): スクロールが発生する親要素のことである。通常、
html
要素や body
要素、あるいはCSSの overflow プロパティによってスクロールが有効になっている要素(例: overflow: scroll;
や overflow: auto;
が指定された div 要素など)がこれに該当する。このコンテナ内でコンテンツがスクロールする。 - スナップターゲット (Snap Target): スクロールスナップが発生する際に、スクロールコンテナの特定の位置(スナップポート)に吸着するように停止する対象となる子要素のことである。これらの要素は、スクロールコンテナ内で特定の位置に「スナップ」する。
ページ内リンクやスクロールスナップ時、固定ヘッダによるコンテンツの隠れや不正確な停止位置は問題となることがある。これらをCSSで調整するのが scroll-padding-top
と scroll-margin-top
である。両者は似ているが、役割と適用対象が異なる。
デモ
scroll-padding-top
と scroll-margin-top
の違いを示すデモは以下。
scroll-padding-top とは
scroll-padding-top
は、前述のスクロールコンテナに設定する。
スクロールコンテナ上端に内向きの空間を設け、スクロールポートの有効な上端をオフセットする。これにより、ページ内リンクやスクロールスナップ時の要素の停止位置が下にずれる。
主な特徴:
- 設定対象: スクロールコンテナ
- 効果: スクロールポートの有効な上端(スナップ基準点)を調整
- 用途: 固定ヘッダによるコンテンツ隠れの防止
短いコード例:
html {
scroll-padding-top: 60px;
}
例えば、scroll-padding-top: 60px;
を設定すると、リンク先のセクション上端がビューポート最上部から 60px
下に表示される。
scroll-margin-top とは
scroll-margin-top
は、前述のスナップターゲットとなる子要素に設定する。
スナップターゲット要素の上部にマージンを設け、スナップ計算上の位置に影響を与える。指定値だけ手前(上)で停止するように見える。
主な特徴:
- 設定対象: スクロールスナップする子要素(スナップターゲット)
- 効果: 個々の要素スナップ時の上部オフセットを指定
- 用途: 特定要素のスナップ位置微調整、要素ごとのオフセット設定
短いコード例:
.snap-target-item {
scroll-margin-top: 20px;
}
例えば scroll-margin-top: 20px;
を設定すると、そのセクションは実際の上端から 20px
上でスナップする。
scroll-padding-top と scroll-margin-top の主な違い
特徴 | scroll-padding-top | scroll-margin-top |
---|
設定対象 | スクロールコンテナ (例: html , body , div ) | スナップターゲット要素 (例: section , article , div ) |
影響範囲 | スクロールコンテナ全体のスクロールポートの上端オフセット | 個々のスナップターゲット要素の上部オフセット |
主な目的 | 固定ヘッダ対策など、コンテナ全体の表示領域調整 | 特定要素のスナップ位置の微調整 |
実践的ユースケース
ケース1:固定ヘッダとページ内リンク (scroll-padding-top)
固定ヘッダがある場合、ページ内リンク先がヘッダに隠れることがある。
- 問題点: ページ内リンク先が固定ヘッダに隠れる。
- 解決策: スクロールコンテナに
scroll-padding-top
を設定し、ヘッダ分のオフセットを指定する。
短いコード例:
html {
scroll-padding-top: 70px;
}
scroll-padding-top: 70px;
で、リンク先がヘッダ高さ分(70px
)下に表示され、隠れを防ぐ。
ケース2:特定のセクションのスナップ位置調整 (scroll-margin-top)
スクロールスナップ時、特定セクションのスナップ位置をほかと変えたい場合がある。
- 問題点: 全セクションが同じ位置にスナップし、個別調整が困難である。
- 解決策: 調整したい要素に
scroll-margin-top
を設定する。
短いコード例:
.special-section {
scroll-margin-top: 50px;
}
.special-section
に scroll-margin-top: 50px;
を設定すると、その要素はほかより50px
手前(上)でスナップする。
ケース3:要素ごとのアンカーリンク位置調整 (scroll-margin-top)
特定のアンカーリンク先要素の上部に余白を持たせたい場合がある。
- 問題点: アンカーリンク先が画面上端に密着し窮屈である。
- 解決策: 対象要素に
scroll-margin-top
で余白を設定する。
短いコード例:
#section-heading {
scroll-margin-top: 2rem;
}
#section-heading
に scroll-margin-top: 2rem;
を設定すると、ジャンプ先の上部に2rem
の余白ができる。これは scroll-padding-top
とは独立した設定である。
ケース4:スクロールスナップコンテナ全体のパディング (scroll-padding-top)
スナップコンテナ全体の上部に一律の余白を持たせたい場合がある。
- 問題点: スナップ要素が、画面上端ギリギリで圧迫感がある。
- 解決策: スナップコンテナに
scroll-padding-top
を設定する。
短いコード例:
.snap-container {
scroll-snap-type: y mandatory;
scroll-padding-top: 30px;
}
.snap-container
に scroll-padding-top: 30px;
を設定する。この設定は、スナップ時にコンテナ上部へ常に30px
の余白を作る。
ケース5:固定ヘッダ環境下で、特定のアンカーリンク先の表示位置をさらに調整する (scroll-padding-top と scroll-margin-top の併用)
固定ヘッダ回避に加え、特定のターゲット要素の表示位置に個別のマージンを設けたい場合がある。
- 問題点:
scroll-padding-top
だけでは、固定ヘッダ回避は一律である。特定要素への追加余白は不可である。 - 解決策: スクロールコンテナに
scroll-padding-top
を設定後、微調整したい要素に scroll-margin-top
を設定する。
短いコード例:
html {
scroll-padding-top: 60px;
}
#important-section {
scroll-margin-top: 20px;
}
html
に scroll-padding-top: 60px;
を設定し、ヘッダ回避。次に #important-section
に scroll-margin-top: 20px;
を設定すると、ヘッダ回避位置からさらに20px
の余白ができる。これにより、scroll-padding-top
の基準位置から scroll-margin-top
分オフセットされる。
どちらを使うべきか?判断フローの提案
どちらを使うか迷ったら、以下を考慮する。
- 固定ヘッダ対策が必要か?
→ スクロールコンテナに scroll-padding-top
- 特定要素のスナップ/アンカー位置をほかと変えたいか?
→ 対象要素に scroll-margin-top
- スナップコンテナ全体に一律の余白が必要か?
→ スナップコンテナに scroll-padding-top
- 複数要素に異なるオフセットを個別に設定したいか?
→ 各要素に scroll-margin-top
- 固定ヘッダ対策+特定アンカーの微調整が必要か?
→ scroll-padding-top
と scroll-margin-top
を併用(ケース5参照)
基本は、コンテナ全体なら scroll-padding-top
、個別要素なら scroll-margin-top
である。組み合わせで複雑な要件に対応可能である。
論理プロパティ
書字方向を考慮した論理プロパティもある。
scroll-padding-block-start
(scroll-padding-top
相当)scroll-margin-block-start
(scroll-margin-top
相当)
これらにより、縦書きなどでも意図通りの挙動をさせやすくなる。
まとめ
scroll-padding-top
と scroll-margin-top
はスクロール位置調整に重要である。
scroll-padding-top
:スクロールコンテナに設定し、全体の有効な上端を調整する。固定ヘッダ対策に有効である。scroll-margin-top
:スナップターゲット要素に設定し、個々の表示位置オフセットを調整する。
参考