27 / 30
All 30 in 30 CSS Grid Layouts
- 01Full-Bleed Layout
- 02Sticky Sidebar Grid
- 03Responsive Media Gallery
- 04Modern Holy Grail
- 05Dynamic Data Grid
- 06Card Stack Overlay
- 07Holy Grail
- 0812-Column Grid
- 09Bento Box
- 10Magazine Editorial
- 11RAM Auto-Fit
- 12Quantity Query
- 13Pinterest Masonry
- 14Hexagonal Honeycomb
- 15Subgrid Card
- 16Dashboard Skeleton
- 17Pricing Table
- 18Kanban Board
- 19Aspect-Ratio Tiles
- 20Container-Query Card
- 21Diagonal Skew Grid
- 22Asymmetric Splash
- 23Mosaic Photo Wall
- 24Dense Packing
- 25Numbered Steps Track
- 26Mac App Sidebar
- 27Scroll-Snap Slider
- 28Aurora Map
- 29Logo Wall
- 30Periodic Table
Scroll-Snap Slider
A native-feeling carousel with zero carousel library: a column-flow grid inside a snap container, slides centered by scroll-snap-align, momentum and touch physics free from the browser. Edge peeking shows there's more to scroll — the affordance JS sliders fake with padding math.
Build layouts like this from scratch: CSS Grid templates, areas & responsive design
ZTM · Fundamentals of CSS Grid · 30‑day money-back guarantee · Affiliate link
The code
<section class="cgl-27" aria-label="Scroll snap slider demo">
<div class="cgl-27__rail" role="group" aria-label="Featured slides">
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.55 0.16 330),oklch(0.3 0.1 300))"><h4>Native physics</h4><p>Momentum, rubber-band, touch — all free.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.5 0.15 260),oklch(0.28 0.09 290))"><h4>snap-align: center</h4><p>The browser settles each slide mid-view.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.55 0.14 200),oklch(0.3 0.08 240))"><h4>78% columns</h4><p>Neighbours peek — the honest 'more here' cue.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.6 0.13 150),oklch(0.32 0.08 180))"><h4>Zero libraries</h4><p>Delete the carousel dependency.</p></article>
</div>
</section><section class="cgl-27" aria-label="Scroll snap slider demo">
<div class="cgl-27__rail" role="group" aria-label="Featured slides">
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.55 0.16 330),oklch(0.3 0.1 300))"><h4>Native physics</h4><p>Momentum, rubber-band, touch — all free.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.5 0.15 260),oklch(0.28 0.09 290))"><h4>snap-align: center</h4><p>The browser settles each slide mid-view.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.55 0.14 200),oklch(0.3 0.08 240))"><h4>78% columns</h4><p>Neighbours peek — the honest 'more here' cue.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.6 0.13 150),oklch(0.32 0.08 180))"><h4>Zero libraries</h4><p>Delete the carousel dependency.</p></article>
</div>
</section>.cgl-27,
.cgl-27 *,
.cgl-27 *::before,
.cgl-27 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cgl-27 {
width: 100%;
min-height: 100vh;
--bg: oklch(0.14 0.02 310);
font-family: system-ui,sans-serif;
background: var(--bg);
padding: 1.6rem 0;
}
.cgl-27 .cgl-27__rail {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 78%;
gap: 14px;
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
padding-inline: 11%;
padding-block-end: 10px;
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}
.cgl-27 .cgl-27__slide {
scroll-snap-align: center;
aspect-ratio: 16/8;
border-radius: 18px;
background: var(--g);
padding: 1.4rem;
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: .4rem;
border: 1px solid oklch(1 0 0/.14);
}
.cgl-27 h4 {
font-size: 1.1rem;
color: white;
}
.cgl-27 .cgl-27__slide p {
font-size: .8rem;
color: oklch(0.85 0.03 310);
}
.cgl-27 .cgl-27__slide:focus-visible {
outline: 3px solid oklch(0.8 0.14 330);
outline-offset: 3px;
}.cgl-27,
.cgl-27 *,
.cgl-27 *::before,
.cgl-27 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cgl-27 {
width: 100%;
min-height: 100vh;
--bg: oklch(0.14 0.02 310);
font-family: system-ui,sans-serif;
background: var(--bg);
padding: 1.6rem 0;
}
.cgl-27 .cgl-27__rail {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 78%;
gap: 14px;
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
padding-inline: 11%;
padding-block-end: 10px;
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}
.cgl-27 .cgl-27__slide {
scroll-snap-align: center;
aspect-ratio: 16/8;
border-radius: 18px;
background: var(--g);
padding: 1.4rem;
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: .4rem;
border: 1px solid oklch(1 0 0/.14);
}
.cgl-27 h4 {
font-size: 1.1rem;
color: white;
}
.cgl-27 .cgl-27__slide p {
font-size: .8rem;
color: oklch(0.85 0.03 310);
}
.cgl-27 .cgl-27__slide:focus-visible {
outline: 3px solid oklch(0.8 0.14 330);
outline-offset: 3px;
}/* No JavaScript — a column-flow grid in a snap container; the browser supplies all carousel physics. */
/* No JavaScript — a column-flow grid in a snap container; the browser supplies all carousel physics. */Here's a working CSS Grid Layout from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Scroll-Snap Slider
Source: https://codefronts.com/layouts/css-grid-layouts/scroll-snap-slider/
A native-feeling carousel with zero carousel library: a column-flow grid inside a snap container, slides centered by scroll-snap-align, momentum and touch physics free from the browser. Edge peeking shows there's more to scroll — the affordance JS sliders fake with padding math.
## HTML
```html
<section class="cgl-27" aria-label="Scroll snap slider demo">
<div class="cgl-27__rail" role="group" aria-label="Featured slides">
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.55 0.16 330),oklch(0.3 0.1 300))"><h4>Native physics</h4><p>Momentum, rubber-band, touch — all free.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.5 0.15 260),oklch(0.28 0.09 290))"><h4>snap-align: center</h4><p>The browser settles each slide mid-view.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.55 0.14 200),oklch(0.3 0.08 240))"><h4>78% columns</h4><p>Neighbours peek — the honest 'more here' cue.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.6 0.13 150),oklch(0.32 0.08 180))"><h4>Zero libraries</h4><p>Delete the carousel dependency.</p></article>
</div>
</section>
```
## CSS
```css
.cgl-27,
.cgl-27 *,
.cgl-27 *::before,
.cgl-27 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cgl-27 {
width: 100%;
min-height: 100vh;
--bg: oklch(0.14 0.02 310);
font-family: system-ui,sans-serif;
background: var(--bg);
padding: 1.6rem 0;
}
.cgl-27 .cgl-27__rail {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 78%;
gap: 14px;
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
padding-inline: 11%;
padding-block-end: 10px;
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}
.cgl-27 .cgl-27__slide {
scroll-snap-align: center;
aspect-ratio: 16/8;
border-radius: 18px;
background: var(--g);
padding: 1.4rem;
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: .4rem;
border: 1px solid oklch(1 0 0/.14);
}
.cgl-27 h4 {
font-size: 1.1rem;
color: white;
}
.cgl-27 .cgl-27__slide p {
font-size: .8rem;
color: oklch(0.85 0.03 310);
}
.cgl-27 .cgl-27__slide:focus-visible {
outline: 3px solid oklch(0.8 0.14 330);
outline-offset: 3px;
}
```
## JavaScript
```js
/* No JavaScript — a column-flow grid in a snap container; the browser supplies all carousel physics. */
```Here's a working CSS Grid Layout from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Scroll-Snap Slider
Source: https://codefronts.com/layouts/css-grid-layouts/scroll-snap-slider/
A native-feeling carousel with zero carousel library: a column-flow grid inside a snap container, slides centered by scroll-snap-align, momentum and touch physics free from the browser. Edge peeking shows there's more to scroll — the affordance JS sliders fake with padding math.
## HTML
```html
<section class="cgl-27" aria-label="Scroll snap slider demo">
<div class="cgl-27__rail" role="group" aria-label="Featured slides">
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.55 0.16 330),oklch(0.3 0.1 300))"><h4>Native physics</h4><p>Momentum, rubber-band, touch — all free.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.5 0.15 260),oklch(0.28 0.09 290))"><h4>snap-align: center</h4><p>The browser settles each slide mid-view.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.55 0.14 200),oklch(0.3 0.08 240))"><h4>78% columns</h4><p>Neighbours peek — the honest 'more here' cue.</p></article>
<article class="cgl-27__slide" tabindex="0" style="--g:linear-gradient(130deg,oklch(0.6 0.13 150),oklch(0.32 0.08 180))"><h4>Zero libraries</h4><p>Delete the carousel dependency.</p></article>
</div>
</section>
```
## CSS
```css
.cgl-27,
.cgl-27 *,
.cgl-27 *::before,
.cgl-27 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cgl-27 {
width: 100%;
min-height: 100vh;
--bg: oklch(0.14 0.02 310);
font-family: system-ui,sans-serif;
background: var(--bg);
padding: 1.6rem 0;
}
.cgl-27 .cgl-27__rail {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 78%;
gap: 14px;
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
padding-inline: 11%;
padding-block-end: 10px;
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}
.cgl-27 .cgl-27__slide {
scroll-snap-align: center;
aspect-ratio: 16/8;
border-radius: 18px;
background: var(--g);
padding: 1.4rem;
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: .4rem;
border: 1px solid oklch(1 0 0/.14);
}
.cgl-27 h4 {
font-size: 1.1rem;
color: white;
}
.cgl-27 .cgl-27__slide p {
font-size: .8rem;
color: oklch(0.85 0.03 310);
}
.cgl-27 .cgl-27__slide:focus-visible {
outline: 3px solid oklch(0.8 0.14 330);
outline-offset: 3px;
}
```
## JavaScript
```js
/* No JavaScript — a column-flow grid in a snap container; the browser supplies all carousel physics. */
```How this works
The rail is grid-auto-flow: column; grid-auto-columns: 78% inside overflow-x: auto; scroll-snap-type: x mandatory. Each slide's scroll-snap-align: center makes the browser settle it mid-viewport — with 78% columns, the neighbours peek 11% on each side. All physics (momentum, rubber-banding, touch, trackpad, keyboard) is native scrolling, which no JS carousel replicates faithfully.
scroll-behavior: smooth upgrades anchor jumps if you add prev/next links; overscroll-behavior-x: contain keeps a swipe past the last slide from triggering browser back-navigation. Slides are focusable <article>s so keyboard users can Tab through — and because it's real scrolling, Tab automatically brings each slide into view.
Make it yours
- Peek amount = 100% − auto-columns %; 90% columns ≈ subtle 5% peeks.
- Snap start instead of center for gallery-style leading alignment (pair with scroll-padding-inline).
- Add prev/next as anchor links to slide ids — smooth-scrolled by the browser.
- Stack a dot indicator with scroll-driven animations (scroll-timeline) where supported — pure-CSS active dots.
Gotchas — read before shipping
- mandatory snap on content TALLER than the viewport traps vertical scrolling — for mixed-height slides use proximity.
- Don't hide the scrollbar without providing visible affordance (the peeks do that here); invisible scrolling fails discoverability.
- iOS momentum + mandatory snap occasionally skips a slide on hard flicks — acceptable native behaviour, don't fight it with JS.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 15.4+ | 113+ | 111+ |
Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome 69+.
Scroll snap has been interoperable since 2019 — this is among the most deployable demos in the set.