scroll-padding
Inset a scroll container’s preferred viewing region without changing layout.
Overview
| Class | Declarations |
|---|---|
scroll-p:<size> | scroll-padding: <size>;
|
scroll-p:<vertical>|<horizontal> | scroll-padding: <vertical> <horizontal>;
|
scroll-p:<top>|<horizontal>|<bottom> | scroll-padding: <top> <horizontal> <bottom>;
|
scroll-p:<top>|<right>|<bottom>|<left> | scroll-padding: <top> <right> <bottom> <left>;
|
scroll-pt:<size> | scroll-padding-top: <size>;
|
scroll-pr:<size> | scroll-padding-right: <size>;
|
scroll-pb:<size> | scroll-padding-bottom: <size>;
|
scroll-pl:<size> | scroll-padding-left: <size>;
|
scroll-px:<size> | scroll-padding-inline: <size>;
|
scroll-px:<inline-start>|<inline-end> | scroll-padding-inline: <inline-start> <inline-end>;
|
scroll-py:<size> | scroll-padding-block: <size>;
|
scroll-py:<block-start>|<block-end> | scroll-padding-block: <block-start> <block-end>;
|
scroll-pxs:<size> | scroll-padding-inline-start: <size>;
|
scroll-pxe:<size> | scroll-padding-inline-end: <size>;
|
scroll-pys:<size> | scroll-padding-block-start: <size>;
|
scroll-pye:<size> | scroll-padding-block-end: <size>;
|
Examples
Pad the scroll container
scroll-p:* insets the container’s preferred viewing region. Activate Details to leave 12px above it. Scroll padding changes scroll alignment without adding layout padding or moving the content before scrolling.
<div id="scrollport" class="overflow-y:auto h:14rem scroll-p-sm" tabindex="0" aria-label="Scrollable collection"> <section id="overview" class="h-3xs"> <strong>Overview</strong> <p>Collect the decisions and shared assets for this project in one place.</p> </section> <section id="details" class="h-3xs"> <strong>Details</strong> <p>Review the structure, spacing and behavior before preparing the final handoff.</p> </section> <section id="resources" class="h-3xs"> <strong>Resources</strong> <p>Keep source files and supporting notes beside the finished collection.</p> </section></div>Generated CSS
@layer theme { :root, :host { --spacing-sm: .75rem }}@layer utilities { .scroll-p-sm { scroll-padding: var(--spacing-sm) }}The destination controls use the browser’s scroll-into-view behavior. The same offset applies to an ordinary fragment link such as <a href="#details">Details</a>.
Reserve space for fixed headers
scroll-pt:* keeps scroll-into-view destinations below an obstruction at the top of the scrollport. Here the sticky header is 48px tall and scroll-pt-3xl reserves 64px, including a 16px gap.
<div id="scrollport" class="overflow-y:auto h:14rem scroll-pt-3xl" tabindex="0" aria-label="Scrollable collection"> <header class="sticky top z:1 h:3rem">Collection navigation</header> <section id="overview" class="h-3xs"> <strong>Overview</strong> <p>Collect the decisions and shared assets for this project in one place.</p> </section> <section id="details" class="h-3xs"> <strong>Details</strong> <p>Review the structure, spacing and behavior before preparing the final handoff.</p> </section> <section id="resources" class="h-3xs"> <strong>Resources</strong> <p>Keep source files and supporting notes beside the finished collection.</p> </section></div>Generated CSS
@layer theme { :root, :host { --spacing-3xl: 4rem }}@layer utilities { .scroll-pt-3xl { scroll-padding-top: var(--spacing-3xl) }}Pad horizontal snapping
scroll-px:* insets the horizontal snapport. This track also uses ordinary px-md to create real space at its first and last edges. Scroll padding alone does not add that layout space. Choose Panel 2 to inspect the 16px alignment inset.
<div id="scrollport" class="flex overflow-x:auto gap-md px-md scroll-px-md scroll-snap-type:x|mandatory" tabindex="0" aria-label="Horizontal panels"> <article id="panel-1" class="flex-shrink:0 h:9rem w:12rem snap-start">Panel 1</article> <article id="panel-2" class="flex-shrink:0 h:9rem w:12rem snap-start">Panel 2</article> <article id="panel-3" class="flex-shrink:0 h:9rem w:12rem snap-start">Panel 3</article> <article id="panel-4" class="flex-shrink:0 h:9rem w:12rem snap-start">Panel 4</article> <article id="panel-5" class="flex-shrink:0 h:9rem w:12rem snap-start">Panel 5</article> <article id="panel-6" class="flex-shrink:0 h:9rem w:12rem snap-start">Panel 6</article></div>Generated CSS
@layer theme { :root, :host { --spacing-md: 1rem }}@layer utilities { .scroll-px-md { scroll-padding-inline: var(--spacing-md) }}Apply conditionally
Use selectors and conditional queries to apply the change only when its condition matches. The viewing inset is 12px on all sides by default, with 32px at the top from sm. Resize and activate Details again to apply the new viewing region.
<div id="scrollport" class="overflow-y:auto h:14rem scroll-p-sm scroll-pt-xl@sm" tabindex="0" aria-label="Scrollable collection"> <section id="overview" class="h-3xs"> <strong>Overview</strong> <p>Collect the decisions and shared assets for this project in one place.</p> </section> <section id="details" class="h-3xs"> <strong>Details</strong> <p>Review the structure, spacing and behavior before preparing the final handoff.</p> </section> <section id="resources" class="h-3xs"> <strong>Resources</strong> <p>Keep source files and supporting notes beside the finished collection.</p> </section></div>The destination controls use the browser’s scroll-into-view behavior. The same offset applies to an ordinary fragment link such as <a href="#details">Details</a>.