27 / 30
All 30 in 30 Tailwind CSS Grid Layouts
- 01Tailwind Full-Bleed Article Layout for Long-Form Editorial
- 02Tailwind Docs Layout with Sticky Table of Contents
- 03Tailwind Photo Gallery Grid with auto-fill and Real Images
- 04Tailwind Holy Grail Page Layout for a News Site
- 05Tailwind Data Table with Subgrid Rows and Status Pills
- 06Tailwind Overlapping Card Hero for a Case Study
- 07Tailwind Help Center Layout with Fixed Sidebars
- 08Tailwind 12 Column Grid System for Marketing Pages
- 09Tailwind Bento Grid for a Product Feature Section
- 10Tailwind Magazine Spread Layout with Overlapping Headline
- 11Tailwind Responsive Card Grid for an Integrations Directory
- 12Tailwind CMS Category Grid that Compacts Itself with has()
- 13Tailwind Masonry Layout for a Saved Ideas Board
- 14Tailwind Hexagon Team Grid with clip-path Avatars
- 15Tailwind Subgrid Cards with Perfectly Aligned Buttons
- 16Tailwind Analytics Dashboard Layout with Grid App Shell
- 17Tailwind Pricing Table with Subgrid and a Featured Plan
- 18Tailwind Kanban Board with Scroll Snap Columns
- 19Tailwind Video Thumbnail Grid with Zero Layout Shift
- 20Tailwind Container Query Card for Reusable Article Teasers
- 21Tailwind Diagonal Section Band with skewY Counter-Skew
- 22Tailwind Asymmetric Poster Hero with Layered Grid Regions
- 23Tailwind Mosaic Photo Wall with a Designed Span Sequence
- 24Tailwind Dense Grid Packing for a Mixed-Size Asset Library
- 25Tailwind Onboarding Stepper with CSS Counters
- 26Tailwind macOS Window Layout with Vibrancy Sidebar
- 27Tailwind Scroll Snap Carousel with Peeking Slides
- 28Tailwind Status Map UI with Grid Coordinate Pins
- 29Tailwind Logo Wall with 1px Gap Hairline Dividers
- 30Tailwind Periodic Table Layout with Grid Coordinates
Tailwind Scroll Snap Carousel with Peeking Slides
A destination carousel with native physics and no library: 78% slides centred by snap-center, neighbours peeking at both edges, real photography and a price line per card. Momentum, rubber-banding and keyboard scrolling come from the browser.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tgx-27 w-full min-h-svh bg-tgx27-bg font-tgx27-sans py-9 grid content-center gap-4">
<header class="px-[11%] flex items-end justify-between gap-4 flex-wrap">
<div class="flex flex-col gap-1">
<p class="text-[0.66rem] tracking-[0.18em] uppercase text-tgx27-accent">Meridian Travel</p>
<h2 class="text-[1.35rem] font-semibold text-white tracking-[-0.01em]">Trips leaving in October</h2>
</div>
<p class="text-[0.74rem] text-tgx27-dim">Swipe, drag or Tab through</p>
</header>
<div role="group" aria-label="Featured trips" class="grid grid-flow-col auto-cols-[78%] gap-4 overflow-x-auto overscroll-x-contain snap-x snap-mandatory scroll-smooth px-[11%] pb-3">
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=900&h=506&q=80&auto=format&fit=crop" alt="Still lake below a wooded ridge at dusk" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">6 nights · guided</p>
<h3 class="text-[1.15rem] font-semibold text-white">Kuusamo lakes</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Cabins, canoes and the first frost. From <span class="tabular-nums font-medium text-white">£1,240</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1500530855697-b586d89ba3ee?w=900&h=506&q=80&auto=format&fit=crop" alt="Rock face rising into mist above a valley" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">8 nights · self-guided</p>
<h3 class="text-[1.15rem] font-semibold text-white">Lofoten crossing</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Ferry hops and fishing villages. From <span class="tabular-nums font-medium text-white">£1,880</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1513635269975-59663e0ac1ad?w=900&h=506&q=80&auto=format&fit=crop" alt="City street at night with lights reflected on wet pavement" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">3 nights · city</p>
<h3 class="text-[1.15rem] font-semibold text-white">London, off-season</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Galleries before the crowds. From <span class="tabular-nums font-medium text-white">£420</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=900&h=506&q=80&auto=format&fit=crop" alt="Mountain range with cloud sitting in the valley" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">5 nights · walking</p>
<h3 class="text-[1.15rem] font-semibold text-white">Hardanger ridges</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Hut to hut, bags moved for you. From <span class="tabular-nums font-medium text-white">£980</span></p>
</div>
</article>
</div>
</section><section class="tgx-27 w-full min-h-svh bg-tgx27-bg font-tgx27-sans py-9 grid content-center gap-4">
<header class="px-[11%] flex items-end justify-between gap-4 flex-wrap">
<div class="flex flex-col gap-1">
<p class="text-[0.66rem] tracking-[0.18em] uppercase text-tgx27-accent">Meridian Travel</p>
<h2 class="text-[1.35rem] font-semibold text-white tracking-[-0.01em]">Trips leaving in October</h2>
</div>
<p class="text-[0.74rem] text-tgx27-dim">Swipe, drag or Tab through</p>
</header>
<div role="group" aria-label="Featured trips" class="grid grid-flow-col auto-cols-[78%] gap-4 overflow-x-auto overscroll-x-contain snap-x snap-mandatory scroll-smooth px-[11%] pb-3">
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=900&h=506&q=80&auto=format&fit=crop" alt="Still lake below a wooded ridge at dusk" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">6 nights · guided</p>
<h3 class="text-[1.15rem] font-semibold text-white">Kuusamo lakes</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Cabins, canoes and the first frost. From <span class="tabular-nums font-medium text-white">£1,240</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1500530855697-b586d89ba3ee?w=900&h=506&q=80&auto=format&fit=crop" alt="Rock face rising into mist above a valley" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">8 nights · self-guided</p>
<h3 class="text-[1.15rem] font-semibold text-white">Lofoten crossing</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Ferry hops and fishing villages. From <span class="tabular-nums font-medium text-white">£1,880</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1513635269975-59663e0ac1ad?w=900&h=506&q=80&auto=format&fit=crop" alt="City street at night with lights reflected on wet pavement" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">3 nights · city</p>
<h3 class="text-[1.15rem] font-semibold text-white">London, off-season</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Galleries before the crowds. From <span class="tabular-nums font-medium text-white">£420</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=900&h=506&q=80&auto=format&fit=crop" alt="Mountain range with cloud sitting in the valley" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">5 nights · walking</p>
<h3 class="text-[1.15rem] font-semibold text-white">Hardanger ridges</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Hut to hut, bags moved for you. From <span class="tabular-nums font-medium text-white">£980</span></p>
</div>
</article>
</div>
</section>@import "tailwindcss";
@theme {
--color-tgx27-bg: #191225;
--color-tgx27-bg: oklch(0.18 0.02 310);
--color-tgx27-dim: #b2a4c4;
--color-tgx27-dim: oklch(0.75 0.04 310);
--color-tgx27-slidedim: #e6dcf0;
--color-tgx27-slidedim: oklch(0.92 0.02 310);
--color-tgx27-accent: #d79ae0;
--color-tgx27-accent: oklch(0.79 0.12 320);
--color-tgx27-ring: #e39ad0;
--color-tgx27-ring: oklch(0.8 0.14 330);
--font-tgx27-sans: 'Inter Tight', system-ui, sans-serif;
}
.tgx-27 {
width: 100%;
min-height: 100svh;
/* Thin coloured scrollbar: no utility, and worth keeping as the visible
affordance this pattern's discoverability depends on. */
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}@import "tailwindcss";
@theme {
--color-tgx27-bg: #191225;
--color-tgx27-bg: oklch(0.18 0.02 310);
--color-tgx27-dim: #b2a4c4;
--color-tgx27-dim: oklch(0.75 0.04 310);
--color-tgx27-slidedim: #e6dcf0;
--color-tgx27-slidedim: oklch(0.92 0.02 310);
--color-tgx27-accent: #d79ae0;
--color-tgx27-accent: oklch(0.79 0.12 320);
--color-tgx27-ring: #e39ad0;
--color-tgx27-ring: oklch(0.8 0.14 330);
--font-tgx27-sans: 'Inter Tight', system-ui, sans-serif;
}
.tgx-27 {
width: 100%;
min-height: 100svh;
/* Thin coloured scrollbar: no utility, and worth keeping as the visible
affordance this pattern's discoverability depends on. */
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tgx27-bg: #191225;
--color-tgx27-bg: oklch(0.18 0.02 310);
--color-tgx27-dim: #b2a4c4;
--color-tgx27-dim: oklch(0.75 0.04 310);
--color-tgx27-slidedim: #e6dcf0;
--color-tgx27-slidedim: oklch(0.92 0.02 310);
--color-tgx27-accent: #d79ae0;
--color-tgx27-accent: oklch(0.79 0.12 320);
--color-tgx27-ring: #e39ad0;
--color-tgx27-ring: oklch(0.8 0.14 330);
--font-tgx27-sans: 'Inter Tight', system-ui, sans-serif;
}
.tgx-27 {
width: 100%;
min-height: 100svh;
/* Thin coloured scrollbar: no utility, and worth keeping as the visible
affordance this pattern's discoverability depends on. */
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}@import "tailwindcss";
@theme {
--color-tgx27-bg: #191225;
--color-tgx27-bg: oklch(0.18 0.02 310);
--color-tgx27-dim: #b2a4c4;
--color-tgx27-dim: oklch(0.75 0.04 310);
--color-tgx27-slidedim: #e6dcf0;
--color-tgx27-slidedim: oklch(0.92 0.02 310);
--color-tgx27-accent: #d79ae0;
--color-tgx27-accent: oklch(0.79 0.12 320);
--color-tgx27-ring: #e39ad0;
--color-tgx27-ring: oklch(0.8 0.14 330);
--font-tgx27-sans: 'Inter Tight', system-ui, sans-serif;
}
.tgx-27 {
width: 100%;
min-height: 100svh;
/* Thin coloured scrollbar: no utility, and worth keeping as the visible
affordance this pattern's discoverability depends on. */
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://images.unsplash.com"> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;600;700&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://images.unsplash.com">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Photographic slides need a scrim before text goes on them; the gradient overlay is a sibling layer rather than a background on the copy, so the image can still be swapped freely.
- Every scroll-snap property has a utility, so the rail's whole behaviour reads end to end in one class list.
- Product upgrade: four gradient panels became four sellable trips with duration, type and a from-price; the header explains the interaction, which the original left to discovery.
Here's a working CSS demo 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: Tailwind Scroll Snap Carousel with Peeking Slides
Source: https://codefronts.com/layouts/tailwind-css-grid-layouts/tailwind-scroll-snap-carousel-peeking-slides/
A destination carousel with native physics and no library: 78% slides centred by snap-center, neighbours peeking at both edges, real photography and a price line per card. Momentum, rubber-banding and keyboard scrolling come from the browser.
## HTML
```html
<section class="tgx-27 w-full min-h-svh bg-tgx27-bg font-tgx27-sans py-9 grid content-center gap-4">
<header class="px-[11%] flex items-end justify-between gap-4 flex-wrap">
<div class="flex flex-col gap-1">
<p class="text-[0.66rem] tracking-[0.18em] uppercase text-tgx27-accent">Meridian Travel</p>
<h2 class="text-[1.35rem] font-semibold text-white tracking-[-0.01em]">Trips leaving in October</h2>
</div>
<p class="text-[0.74rem] text-tgx27-dim">Swipe, drag or Tab through</p>
</header>
<div role="group" aria-label="Featured trips" class="grid grid-flow-col auto-cols-[78%] gap-4 overflow-x-auto overscroll-x-contain snap-x snap-mandatory scroll-smooth px-[11%] pb-3">
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=900&h=506&q=80&auto=format&fit=crop" alt="Still lake below a wooded ridge at dusk" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">6 nights · guided</p>
<h3 class="text-[1.15rem] font-semibold text-white">Kuusamo lakes</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Cabins, canoes and the first frost. From <span class="tabular-nums font-medium text-white">£1,240</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1500530855697-b586d89ba3ee?w=900&h=506&q=80&auto=format&fit=crop" alt="Rock face rising into mist above a valley" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">8 nights · self-guided</p>
<h3 class="text-[1.15rem] font-semibold text-white">Lofoten crossing</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Ferry hops and fishing villages. From <span class="tabular-nums font-medium text-white">£1,880</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1513635269975-59663e0ac1ad?w=900&h=506&q=80&auto=format&fit=crop" alt="City street at night with lights reflected on wet pavement" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">3 nights · city</p>
<h3 class="text-[1.15rem] font-semibold text-white">London, off-season</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Galleries before the crowds. From <span class="tabular-nums font-medium text-white">£420</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=900&h=506&q=80&auto=format&fit=crop" alt="Mountain range with cloud sitting in the valley" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">5 nights · walking</p>
<h3 class="text-[1.15rem] font-semibold text-white">Hardanger ridges</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Hut to hut, bags moved for you. From <span class="tabular-nums font-medium text-white">£980</span></p>
</div>
</article>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgx27-bg: #191225;
--color-tgx27-bg: oklch(0.18 0.02 310);
--color-tgx27-dim: #b2a4c4;
--color-tgx27-dim: oklch(0.75 0.04 310);
--color-tgx27-slidedim: #e6dcf0;
--color-tgx27-slidedim: oklch(0.92 0.02 310);
--color-tgx27-accent: #d79ae0;
--color-tgx27-accent: oklch(0.79 0.12 320);
--color-tgx27-ring: #e39ad0;
--color-tgx27-ring: oklch(0.8 0.14 330);
--font-tgx27-sans: 'Inter Tight', system-ui, sans-serif;
}
.tgx-27 {
width: 100%;
min-height: 100svh;
/* Thin coloured scrollbar: no utility, and worth keeping as the visible
affordance this pattern's discoverability depends on. */
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}
```Here's a working CSS demo 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: Tailwind Scroll Snap Carousel with Peeking Slides
Source: https://codefronts.com/layouts/tailwind-css-grid-layouts/tailwind-scroll-snap-carousel-peeking-slides/
A destination carousel with native physics and no library: 78% slides centred by snap-center, neighbours peeking at both edges, real photography and a price line per card. Momentum, rubber-banding and keyboard scrolling come from the browser.
## HTML
```html
<section class="tgx-27 w-full min-h-svh bg-tgx27-bg font-tgx27-sans py-9 grid content-center gap-4">
<header class="px-[11%] flex items-end justify-between gap-4 flex-wrap">
<div class="flex flex-col gap-1">
<p class="text-[0.66rem] tracking-[0.18em] uppercase text-tgx27-accent">Meridian Travel</p>
<h2 class="text-[1.35rem] font-semibold text-white tracking-[-0.01em]">Trips leaving in October</h2>
</div>
<p class="text-[0.74rem] text-tgx27-dim">Swipe, drag or Tab through</p>
</header>
<div role="group" aria-label="Featured trips" class="grid grid-flow-col auto-cols-[78%] gap-4 overflow-x-auto overscroll-x-contain snap-x snap-mandatory scroll-smooth px-[11%] pb-3">
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?w=900&h=506&q=80&auto=format&fit=crop" alt="Still lake below a wooded ridge at dusk" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">6 nights · guided</p>
<h3 class="text-[1.15rem] font-semibold text-white">Kuusamo lakes</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Cabins, canoes and the first frost. From <span class="tabular-nums font-medium text-white">£1,240</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1500530855697-b586d89ba3ee?w=900&h=506&q=80&auto=format&fit=crop" alt="Rock face rising into mist above a valley" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">8 nights · self-guided</p>
<h3 class="text-[1.15rem] font-semibold text-white">Lofoten crossing</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Ferry hops and fishing villages. From <span class="tabular-nums font-medium text-white">£1,880</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1513635269975-59663e0ac1ad?w=900&h=506&q=80&auto=format&fit=crop" alt="City street at night with lights reflected on wet pavement" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">3 nights · city</p>
<h3 class="text-[1.15rem] font-semibold text-white">London, off-season</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Galleries before the crowds. From <span class="tabular-nums font-medium text-white">£420</span></p>
</div>
</article>
<article tabindex="0" class="snap-center relative aspect-[16/9] rounded-2xl overflow-hidden border border-white/15 focus-visible:outline-[3px] focus-visible:outline-tgx27-ring focus-visible:outline-offset-[3px]">
<img src="https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=900&h=506&q=80&auto=format&fit=crop" alt="Mountain range with cloud sitting in the valley" loading="lazy" class="absolute inset-0 w-full h-full object-cover">
<div class="absolute inset-0 bg-[linear-gradient(180deg,transparent_35%,oklch(0.12_0.02_300/0.88))]"></div>
<div class="relative h-full flex flex-col justify-end gap-1 p-5">
<p class="text-[0.66rem] tracking-[0.16em] uppercase text-tgx27-ring">5 nights · walking</p>
<h3 class="text-[1.15rem] font-semibold text-white">Hardanger ridges</h3>
<p class="text-[0.8rem] text-tgx27-slidedim">Hut to hut, bags moved for you. From <span class="tabular-nums font-medium text-white">£980</span></p>
</div>
</article>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgx27-bg: #191225;
--color-tgx27-bg: oklch(0.18 0.02 310);
--color-tgx27-dim: #b2a4c4;
--color-tgx27-dim: oklch(0.75 0.04 310);
--color-tgx27-slidedim: #e6dcf0;
--color-tgx27-slidedim: oklch(0.92 0.02 310);
--color-tgx27-accent: #d79ae0;
--color-tgx27-accent: oklch(0.79 0.12 320);
--color-tgx27-ring: #e39ad0;
--color-tgx27-ring: oklch(0.8 0.14 330);
--font-tgx27-sans: 'Inter Tight', system-ui, sans-serif;
}
.tgx-27 {
width: 100%;
min-height: 100svh;
/* Thin coloured scrollbar: no utility, and worth keeping as the visible
affordance this pattern's discoverability depends on. */
scrollbar-width: thin;
scrollbar-color: oklch(0.5 0.1 310) transparent;
}
```How this works
All the physics is native. Momentum, trackpad, touch and keyboard — none of which a JS carousel replicates faithfully, all of which come free from overflow-x-auto plus snap utilities.
The peek is arithmetic: slide width plus symmetric padding. 78% columns with 11% inline padding centres a slide and reveals its neighbours, which is the honest 'there is more' affordance.
Make it yours
- Peek amount = (100% − slide width) ÷ 2.
snap-startplusscroll-pl-*for gallery-style leading alignment.- Prev/next as anchor links to slide ids —
scroll-smoothanimates them, still no JS.
Gotchas — read before shipping
snap-mandatoryon content taller than the viewport traps vertical scrolling; use proximity for mixed heights.- Do not hide the scrollbar without another affordance — the peeks are doing that job.
- iOS momentum plus mandatory snap occasionally skips a slide on hard flicks; that is native behaviour.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Scroll snap has been interoperable since 2019 — among the most deployable demos here.