CSS scroll-padding Property
The scroll-padding property sets the offsets that define the optimal viewing area of a scroll container. It ensures that when an element is scrolled into view, it does not sit flush against the edges of the container.
| auto | The browser determines the offset, which is usually 0px unless otherwise defined by the user agent. |
| <length> | Specifies a fixed distance using units like px, em, or rem to offset the scroll area. |
| <percentage> | Specifies an offset relative to the size of the scroll container's scrollport. |
Code Examples
A basic scroll-snap container where scroll-padding ensures that snapped items sit 20px away from the top edge.
<style>
.scroll-container {
width: 300px;
height: 200px;
overflow-y: scroll;
scroll-snap-type: y mandatory;
scroll-padding: 20px;
border: 2px solid #333333;
}
.item {
width: 100%;
height: 200px;
scroll-snap-align: start;
background: #f0f0f0;
border-bottom: 1px solid #cccccc;
}
</style>
<div class="scroll-container">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>An advanced implementation using scroll-padding on the html element to account for a sticky header, with a JS helper to keep the offset precise.
<style>
html {
scroll-behavior: smooth;
scroll-padding-top: 80px;
}
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
background: #222222;
color: #ffffff;
display: flex;
align-items: center;
padding: 0 20px;
}
section {
height: 100vh;
padding: 20px;
background: #eeeeee;
border-bottom: 2px solid #333333;
}
</style>
<header>Sticky Navigation</header>
<nav>
<a href="#sec1">Section 1</a>
<a href="#sec2">Section 2</a>
</nav>
<section id="sec1"><h1>Section 1 Content</h1></section>
<section id="sec2"><h1>Section 2 Content</h1></section>
<script>
// Example of adjusting padding if header height changes dynamically
const header = document.querySelector("header");
const adjustScrollPadding = () => {
document.documentElement.style.scrollPaddingTop = header.offsetHeight + 20 + "px";
};
window.addEventListener("resize", adjustScrollPadding);
adjustScrollPadding();
</script>Pro Tip
If you have a site where the header height changes on mobile versus desktop, use a CSS variable like "--header-height" and update that variable inside a media query. Then, set your scroll-padding-top to use that variable. This keeps your scroll offsets perfectly synced across all device sizes without writing redundant styles.
Deep Dive
Think of scroll-padding like the safety margin on a piece of paper. When you use anchor links or scroll-snapping, the browser moves the target element to the very top of the scroll container. If you have a sticky header, that header will cover your content. By applying scroll-padding to the container, you are telling the browser, "Hey, the viewport has a restricted area at the top, so stop scrolling once the content reaches this line, not the literal top of the box." This property is a shorthand for top, right, bottom, and left offsets. It does not affect the actual layout or size of child elements; it only influences the "landing position" during scroll operations. It is applied to the scroll container (the parent), whereas scroll-margin is applied to the individual child elements.
Best Practices
Always apply scroll-padding-top to the "html" or "body" element if your site uses a fixed or sticky navigation bar. Use CSS variables to store your header's height so you can easily map that value to your scroll-padding. This ensures that "Jump to Section" links always land with the heading clearly visible below the navigation bar instead of being tucked behind it.
Common Pitfalls
A common mistake is applying scroll-padding to the section elements themselves; remember, padding goes on the container that is doing the scrolling. Another mix-up is confusing this with regular padding. Regular padding creates physical space inside the box that affects layout, while scroll-padding only affects the viewing area during a scroll event. If your scroll-padding seems ignored, check if you are targeting the correct overflow container.
Accessibility
This property is a massive win for keyboard users. When a user tabs through links or focusable elements, the browser automatically scrolls the focused element into view. Without scroll-padding, a sticky header might obscure the focused element, making it impossible for the user to see where their cursor or focus currently resides. Proper offsets ensure that the active focus area is always within the visible portion of the screen.
Dev Data Table: scroll-padding property
| default | auto |
| animatable | yes |
| inherited | no |
| experimental | no |
| year_intro | 2016 |
| year_standard | 2019 |
| js_syntax_1 | element.style.scrollPadding = "20px"; |
| js_syntax_2 | element.style.setProperty("scroll-padding", "20px"); |
| js_note | When manipulating this property via JavaScript, ensure you account for dynamic header heights to keep the scroll offset accurate. |
| browsers | { "Chrome": 69, "Edge": 79, "Firefox": 68, "Safari": 11, "Opera": 56, "Chrome Android": 69, "Safari on iOS": 11, "Samsung Internet": 10.1, "Opera Mobile": 48 } |