CSS scroll-padding-block Property
Sets the scroll padding offsets for both the start and end edges of a scroll container in the block dimension.
| auto | The browser determines the padding, which usually defaults to 0px. |
| <length> | Defines a fixed offset using standard units like px, rem, or vh. |
| <percentage> | Defines the offset as a percentage relative to the scroll container's scrollport size. |
Code Examples
A basic scroll-snap container where each item snaps 50px away from the block edges of the container.
<style>
.scroll-container {
width: 300px;
height: 300px;
overflow-y: scroll;
scroll-snap-type: y mandatory;
scroll-padding-block: 50px;
border: 2px solid #333333;
}
.item {
width: 100%;
height: 100%;
scroll-snap-align: start;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
}
.item:nth-child(odd) { background: #f0f0f0; }
.item:nth-child(even) { background: #cccccc; }
</style>
<div class="scroll-container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>An advanced implementation using CSS variables and JavaScript to ensure anchor links never land behind a fixed navigation bar.
<style>
:root {
--nav-height: 60px;
}
html {
scroll-padding-block-start: var(--nav-height);
scroll-behavior: smooth;
}
nav {
position: fixed;
top: 0;
width: 100%;
height: var(--nav-height);
background: #222222;
color: #ffffff;
display: flex;
align-items: center;
padding: 0 20px;
}
section {
height: 100vh;
padding: 20px;
border-bottom: 1px solid #dddddd;
}
</style>
<nav id="main-nav">Fixed Navigation</nav>
<section id="sec1">Section 1 Content</section>
<section id="sec2">Section 2 Content</section>
<script>
const nav = document.getElementById("main-nav");
// Dynamically update the scroll padding if the nav height changes
window.addEventListener("resize", () => {
const height = nav.offsetHeight + "px";
document.documentElement.style.setProperty("scroll-padding-block-start", height);
console.log("Scroll padding updated to: " + height);
});
</script>Pro Tip
If you have a dynamic header height, you can use a CSS Variable for the value of scroll-padding-block. This allows you to update the variable once in JavaScript whenever the header height changes, and every scroll-snap or anchor jump in your app will instantly respect the new offset.
Deep Dive
Think of the scrollport like a picture frame and your content like the photo inside. If you have a fixed header at the top of your frame, it acts like a piece of tape covering the glass. Without scroll-padding-block, when you jump to a section, the browser aligns the element to the very top edge of the frame, hidden behind that tape. This property creates a "safety zone" or buffer inside the scroll container. It tells the browser, "When you snap or jump to an element, stop this far away from the edges." Because it is a logical property, it maps to the vertical axis in standard horizontal writing modes, but it will automatically flip to the horizontal axis if the writing mode is vertical.
Best Practices
Apply this property to the parent scroll container, not the individual child elements. It is most effective when used on the "html" or "body" tags to handle fixed navigation headers that would otherwise overlap content when a user clicks an anchor link. By using this logical property instead of physical properties like "scroll-padding-top," your layout remains future-proof and responsive to different language directions and writing modes.
Common Pitfalls
A common mistake is trying to use this property on the element you are scrolling to; remember, this belongs on the container that holds the scrollbar. Also, keep in mind that this property only affects the "scrollport" area and does not add actual visual padding or space to the element's box model; it only influences the final resting position of a scroll operation.
Accessibility
This property significantly improves accessibility by preventing "focus-obscuring." When a keyboard user tabs to a link or a screen reader jumps to a heading, this property ensures the target remains visible and is not tucked away under sticky headers or UI overlays, keeping the visual focus clear for the user.
Dev Data Table: scroll-padding-block property
| default | auto |
| animatable | no |
| inherited | no |
| experimental | no |
| year_intro | 2018 |
| year_standard | 2021 |
| js_syntax_1 | element.style.scrollPaddingBlock |
| js_syntax_2 | element.style.setProperty("scroll-padding-block", "20px") |
| js_note | When manipulating logical properties in JavaScript, ensure the browser supports CSS Logical Properties or the layout might not reflect the intended block axis. |
| browsers | { "Chrome": 69, "Edge": 79, "Firefox": 68, "Safari": 14.1, "Opera": 56, "Chrome Android": 69, "Safari on iOS": 14.5, "Samsung Internet": 10.1, "Opera Mobile": 48 } |