Snapport
The container defines the snapping axes.
Explore how a scroll area settles into predictable positions. Change the axis, strictness, block and inline alignment, and the spacing around the snapport and each target.
Drag, use the wheel, or focus the cards with the keyboard to test every snap position.
Dashed line: snapport reduced by scroll-paddingDotted line: area expanded by scroll-margin
The container defines the snapping axes.
Mandatory or proximity changes the pull.
The optimal viewing region moves inward.
The first alignment value controls block.
Each card creates its own snap area.
The second alignment value controls inline.
The snap area grows beyond the border box.
Always can prevent skipping a target.
Focus a card to bring it into view.
<div class="snapport" aria-label="Interactive CSS scroll snap area" tabindex="0">
<article
class="snap-item"
style="--item-color: #ffb38a"
tabindex="0"
>
<span>01</span>
<h2>Snapport</h2>
<p>The container defines the snapping axes.</p>
</article>
<article
class="snap-item"
style="--item-color: #72d6c9"
tabindex="0"
>
<span>02</span>
<h2>Strictness</h2>
<p>Mandatory or proximity changes the pull.</p>
</article>
<article
class="snap-item"
style="--item-color: #b6a8ff"
tabindex="0"
>
<span>03</span>
<h2>Padding</h2>
<p>The optimal viewing region moves inward.</p>
</article>
<article
class="snap-item"
style="--item-color: #ffd166"
tabindex="0"
>
<span>04</span>
<h2>Block axis</h2>
<p>The first alignment value controls block.</p>
</article>
<article
class="snap-item"
style="--item-color: #f7a6c4"
tabindex="0"
>
<span>05</span>
<h2>Snap target</h2>
<p>Each card creates its own snap area.</p>
</article>
<article
class="snap-item"
style="--item-color: #8ecae6"
tabindex="0"
>
<span>06</span>
<h2>Inline axis</h2>
<p>The second alignment value controls inline.</p>
</article>
<article
class="snap-item"
style="--item-color: #a7df9b"
tabindex="0"
>
<span>07</span>
<h2>Margin</h2>
<p>The snap area grows beyond the border box.</p>
</article>
<article
class="snap-item"
style="--item-color: #f6bd60"
tabindex="0"
>
<span>08</span>
<h2>Snap stop</h2>
<p>Always can prevent skipping a target.</p>
</article>
<article
class="snap-item"
style="--item-color: #c7a6ff"
tabindex="0"
>
<span>09</span>
<h2>Keyboard</h2>
<p>Focus a card to bring it into view.</p>
</article>
</div><div class="grid grid-cols-[repeat(3,72%)] auto-rows-[72%] gap-6 inline-[min(100%,36rem)] block-96 m-0 p-0 overflow-auto overscroll-contain snap-both snap-mandatory scroll-p-[32px]" aria-label="Interactive CSS scroll snap area" tabindex="0">
<article
class="box-border grid content-end gap-2 p-[clamp(20px,4vw,32px)] border rounded-2xl text-[#172033] scroll-m-[12px] snap-center snap-normal *:m-0 [&_h2]:text-[clamp(1.75rem,1rem_+_3vw,3rem)] [&>span]:font-extrabold focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#ffb38a_72%,#172033)] bg-[#ffb38a]"
tabindex="0"
>
<span>01</span>
<h2>Snapport</h2>
<p>The container defines the snapping axes.</p>
</article>
<article
class="box-border grid content-end gap-2 p-[clamp(20px,4vw,32px)] border rounded-2xl text-[#172033] scroll-m-[12px] snap-center snap-normal *:m-0 [&_h2]:text-[clamp(1.75rem,1rem_+_3vw,3rem)] [&>span]:font-extrabold focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#72d6c9_72%,#172033)] bg-[#72d6c9]"
tabindex="0"
>
<span>02</span>
<h2>Strictness</h2>
<p>Mandatory or proximity changes the pull.</p>
</article>
<article
class="box-border grid content-end gap-2 p-[clamp(20px,4vw,32px)] border rounded-2xl text-[#172033] scroll-m-[12px] snap-center snap-normal *:m-0 [&_h2]:text-[clamp(1.75rem,1rem_+_3vw,3rem)] [&>span]:font-extrabold focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#b6a8ff_72%,#172033)] bg-[#b6a8ff]"
tabindex="0"
>
<span>03</span>
<h2>Padding</h2>
<p>The optimal viewing region moves inward.</p>
</article>
<article
class="box-border grid content-end gap-2 p-[clamp(20px,4vw,32px)] border rounded-2xl text-[#172033] scroll-m-[12px] snap-center snap-normal *:m-0 [&_h2]:text-[clamp(1.75rem,1rem_+_3vw,3rem)] [&>span]:font-extrabold focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#ffd166_72%,#172033)] bg-[#ffd166]"
tabindex="0"
>
<span>04</span>
<h2>Block axis</h2>
<p>The first alignment value controls block.</p>
</article>
<article
class="box-border grid content-end gap-2 p-[clamp(20px,4vw,32px)] border rounded-2xl text-[#172033] scroll-m-[12px] snap-center snap-normal *:m-0 [&_h2]:text-[clamp(1.75rem,1rem_+_3vw,3rem)] [&>span]:font-extrabold focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#f7a6c4_72%,#172033)] bg-[#f7a6c4]"
tabindex="0"
>
<span>05</span>
<h2>Snap target</h2>
<p>Each card creates its own snap area.</p>
</article>
<article
class="box-border grid content-end gap-2 p-[clamp(20px,4vw,32px)] border rounded-2xl text-[#172033] scroll-m-[12px] snap-center snap-normal *:m-0 [&_h2]:text-[clamp(1.75rem,1rem_+_3vw,3rem)] [&>span]:font-extrabold focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#8ecae6_72%,#172033)] bg-[#8ecae6]"
tabindex="0"
>
<span>06</span>
<h2>Inline axis</h2>
<p>The second alignment value controls inline.</p>
</article>
<article
class="box-border grid content-end gap-2 p-[clamp(20px,4vw,32px)] border rounded-2xl text-[#172033] scroll-m-[12px] snap-center snap-normal *:m-0 [&_h2]:text-[clamp(1.75rem,1rem_+_3vw,3rem)] [&>span]:font-extrabold focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#a7df9b_72%,#172033)] bg-[#a7df9b]"
tabindex="0"
>
<span>07</span>
<h2>Margin</h2>
<p>The snap area grows beyond the border box.</p>
</article>
<article
class="box-border grid content-end gap-2 p-[clamp(20px,4vw,32px)] border rounded-2xl text-[#172033] scroll-m-[12px] snap-center snap-normal *:m-0 [&_h2]:text-[clamp(1.75rem,1rem_+_3vw,3rem)] [&>span]:font-extrabold focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#f6bd60_72%,#172033)] bg-[#f6bd60]"
tabindex="0"
>
<span>08</span>
<h2>Snap stop</h2>
<p>Always can prevent skipping a target.</p>
</article>
<article
class="box-border grid content-end gap-2 p-[clamp(20px,4vw,32px)] border rounded-2xl text-[#172033] scroll-m-[12px] snap-center snap-normal *:m-0 [&_h2]:text-[clamp(1.75rem,1rem_+_3vw,3rem)] [&>span]:font-extrabold focus-visible:outline-4 focus-visible:outline-[#172033] focus-visible:-outline-offset-8 border-[color-mix(in_oklch,#c7a6ff_72%,#172033)] bg-[#c7a6ff]"
tabindex="0"
>
<span>09</span>
<h2>Keyboard</h2>
<p>Focus a card to bring it into view.</p>
</article>
</div>.snapport {
display: grid;
grid-template-columns: repeat(3, 72%);
grid-auto-rows: 72%;
gap: 1.5rem;
inline-size: min(100%, 36rem);
block-size: 24rem;
margin: 0;
padding: 0;
overflow: auto;
overscroll-behavior: contain;
scroll-snap-type: both mandatory;
scroll-padding: 32px;
}
.snap-item {
box-sizing: border-box;
display: grid;
align-content: end;
gap: 0.5rem;
padding: clamp(20px, 4vw, 32px);
border: 1px solid color-mix(in oklch, var(--item-color) 72%, #172033);
border-radius: 1rem;
background: var(--item-color);
color: #172033;
scroll-margin: 12px;
scroll-snap-align: center;
scroll-snap-stop: normal;
}
.snap-item > * {
margin: 0;
}
.snap-item h2 {
font-size: clamp(1.75rem, 1rem + 3vw, 3rem);
}
.snap-item > span {
font-weight: 800;
}
.snap-item:focus-visible {
outline: 4px solid #172033;
outline-offset: -8px;
}.snapport {
display: grid;
grid-template-columns: repeat(3, 72%);
grid-auto-rows: 72%;
gap: 1.5rem;
inline-size: min(100%, 36rem);
block-size: 24rem;
margin: 0;
padding: 0;
overflow: auto;
overscroll-behavior: contain;
scroll-snap-type: both mandatory;
scroll-padding: 32px;
> .snap-item {
box-sizing: border-box;
display: grid;
align-content: end;
gap: 0.5rem;
padding: clamp(20px, 4vw, 32px);
border: 1px solid color-mix(in oklch, var(--item-color) 72%, #172033);
border-radius: 1rem;
background: var(--item-color);
color: #172033;
scroll-margin: 12px;
scroll-snap-align: center;
scroll-snap-stop: normal;
> * {
margin: 0;
}
h2 {
font-size: clamp(1.75rem, 1rem + 3vw, 3rem);
}
> span {
font-weight: 800;
}
&:focus-visible {
outline: 4px solid #172033;
outline-offset: -8px;
}
}
}