scroll-margin adds an outset to a target’s scroll-snap area. It also affects target positioning for operations such as scrollIntoView. It does not reserve normal layout space around the element.
Leave room above a scroll target
Click the button. The target aligns 24px below the scrollport’s top instead of flush against it; that space is a scroll-target adjustment, not a layout margin.
HTML and CSS
HTML
<button
type="button"
onclick="document.getElementById('target').scrollIntoView({block: 'start'})"
>
Scroll to target
</button>
<div
class="viewport"
tabindex="0"
role="region"
aria-label="Scrollable practice area"
>
<div class="spacer">Scroll area begins here.</div>
<p class="target" id="target">Target paragraph</p>
<div class="spacer">Space after the target.</div>
</div>
CSS
.viewport {
height: 150px;
overflow: auto;
border: 2px solid #94a3b8;
}
.spacer {
height: 180px;
background: #eff6ff;
}
.target {
padding: 0.75rem;
background: #bfdbfe;
margin: 0;
}
button {
padding: 0.75rem;
font: inherit;
margin-bottom: 0.5rem;
}
.target {
scroll-margin: 24px 0 0;
}
Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.
Account for a sticky toolbar
The target’s block-start scroll margin accounts for the 40px toolbar. The target stays in its ordinary flow position until the scroll operation occurs.
HTML and CSS
HTML
<button
type="button"
onclick="document.getElementById('target').scrollIntoView({block: 'start'})"
>
Scroll to target
</button>
<div
class="viewport"
tabindex="0"
role="region"
aria-label="Scrollable practice area"
>
<div class="toolbar">Sticky toolbar</div>
<div class="spacer">Scroll area begins here.</div>
<p class="target" id="target">Target paragraph</p>
<div class="spacer">Space after the target.</div>
</div>
CSS
.viewport {
height: 150px;
overflow: auto;
border: 2px solid #94a3b8;
}
.spacer {
height: 180px;
background: #eff6ff;
}
.target {
padding: 0.75rem;
background: #bfdbfe;
margin: 0;
}
button {
padding: 0.75rem;
font: inherit;
margin-bottom: 0.5rem;
}
.toolbar {
position: sticky;
top: 0;
height: 40px;
background: #172554;
color: white;
}
.target {
scroll-margin-block-start: 48px;
}
Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.
Syntax and defaults
The shorthand sets physical top/right/bottom/left scroll margins with the same one-to-four expansion as margin. Initial longhands are zero, and they are not inherited. Values are lengths; percentages are invalid. Use logical longhands such as scroll-margin-block-start when the target’s writing mode should determine the edge.
Common mistakes
Put scroll-margin on the target, not the container. Unlike ordinary margin, it does not move surrounding elements or enlarge the normal layout box. Alignment is constrained by available scrolling range, so a target near the end may not reach the requested position. A later shorthand resets omitted sides.
Learn scroll-padding for a container-wide viewing inset, scroll-snap-align, and position.
Sources and browser support
MDN: scroll-margin describes the syntax and links to the specification and compatibility data. Check individual values in that table when supporting older browsers.