A full-height band of cards you swipe through, where the card nearest the centre is the one in focus — its neighbours sit back, smaller and dimmer. The track is endless by default: past the last card comes the first again. It is the same scroll-snap mechanism as the rail, so touch, keyboard and no-JS all still work; the focus is a scroll-driven animation layered over it, and browsers without that support simply get the rail.
A full-height band, so the specimens below are cramped by the documentation column — use Full page preview on each to see it own the viewport, which is the whole point of it.
A full-height band; the centre card holds focus while its neighbours sit back. An introduction, when a band wants one, is a Section header composed above it.

Editorial
A quiet series shot over one winter, printed small and hung close together.

Identity
A wordmark and a colour that had to survive fog, salt and neon.

Product
Twelve screens, one component library, and no bespoke pages.

Editorial
Long-form layout for a magazine that reads better on a phone.

Studio
The house palette, and the argument for keeping it boring.
<section class="mk-card-carousel mk-card-carousel--full" data-rail data-rail-loop>
<div class="mk-card-carousel__track" data-rail-track data-rail-step="item" tabindex="0" role="group" aria-label="Selected work">
<a class="mk-card" href="#">
<div class="mk-card__media">
<img src="/assets/img/everlasting.jpg" alt="A generated colour field" loading="lazy" decoding="async">
</div>
<div class="mk-card__body">
<p class="mk-eyebrow text-uppercase fw-semibold mb-2">Editorial</p>
<h3 class="mk-card__title">Slow mornings</h3>
<div class="mk-card__reveal">
<div class="mk-card__reveal-inner">
<p class="mb-0">A quiet series shot over one winter, printed small and hung close together.</p>
<p class="mk-card__cta mb-0">
<span class="mk-card__cta-text" aria-hidden="true">Read more</span>
</p>
</div>
</div>
</div>
</a>
<a class="mk-card" href="#">
<div class="mk-card__media">
<img src="/assets/img/everlasting.jpg" alt="A generated colour field" loading="lazy" decoding="async">
</div>
<div class="mk-card__body">
<p class="mk-eyebrow text-uppercase fw-semibold mb-2">Identity</p>
<h3 class="mk-card__title">Harbour light</h3>
<div class="mk-card__reveal">
<div class="mk-card__reveal-inner">
<p class="mb-0">A wordmark and a colour that had to survive fog, salt and neon.</p>
<p class="mk-card__cta mb-0">
<span class="mk-card__cta-text" aria-hidden="true">Read more</span>
</p>
</div>
</div>
</div>
</a>
<a class="mk-card" href="#">
<div class="mk-card__media">
<img src="/assets/img/everlasting.jpg" alt="A generated colour field" loading="lazy" decoding="async">
</div>
<div class="mk-card__body">
<p class="mk-eyebrow text-uppercase fw-semibold mb-2">Product</p>
<h3 class="mk-card__title">Low tide</h3>
<div class="mk-card__reveal">
<div class="mk-card__reveal-inner">
<p class="mb-0">Twelve screens, one component library, and no bespoke pages.</p>
<p class="mk-card__cta mb-0">
<span class="mk-card__cta-text" aria-hidden="true">Read more</span>
</p>
</div>
</div>
</div>
</a>
<a class="mk-card" href="#">
<div class="mk-card__media">
<img src="/assets/img/everlasting.jpg" alt="A generated colour field" loading="lazy" decoding="async">
</div>
<div class="mk-card__body">
<p class="mk-eyebrow text-uppercase fw-semibold mb-2">Editorial</p>
<h3 class="mk-card__title">Long grass</h3>
<div class="mk-card__reveal">
<div class="mk-card__reveal-inner">
<p class="mb-0">Long-form layout for a magazine that reads better on a phone.</p>
<p class="mk-card__cta mb-0">
<span class="mk-card__cta-text" aria-hidden="true">Read more</span>
</p>
</div>
</div>
</div>
</a>
<a class="mk-card" href="#">
<div class="mk-card__media">
<img src="/assets/img/everlasting.jpg" alt="A generated colour field" loading="lazy" decoding="async">
</div>
<div class="mk-card__body">
<p class="mk-eyebrow text-uppercase fw-semibold mb-2">Studio</p>
<h3 class="mk-card__title">Everlasting</h3>
<div class="mk-card__reveal">
<div class="mk-card__reveal-inner">
<p class="mb-0">The house palette, and the argument for keeping it boring.</p>
<p class="mk-card__cta mb-0">
<span class="mk-card__cta-text" aria-hidden="true">Read more</span>
</p>
</div>
</div>
</div>
</a>
</div>
<button class="mk-card-carousel__nav mk-card-carousel__nav--prev" type="button" data-rail-prev aria-label="Previous" hidden>
<i class="bi bi-chevron-left" aria-hidden="true"></i>
</button>
<button class="mk-card-carousel__nav mk-card-carousel__nav--next" type="button" data-rail-next aria-label="Next" hidden>
<i class="bi bi-chevron-right" aria-hidden="true"></i>
</button>
</section> label: Selected work
items: [5 items] The same cards wearing the dark surface — the band a page drops in between two lighter sections.
<section class="mk-card-carousel mk-card-carousel--full surface-dark" id="cards-dark" data-bs-theme="dark" data-rail data-rail-loop>
<div class="mk-card-carousel__track" data-rail-track data-rail-step="item" tabindex="0" role="group" aria-label="Work">
<a class="mk-card" href="#">
<div class="mk-card__media">
<img src="/assets/img/everlasting.jpg" alt="A generated colour field" loading="lazy" decoding="async">
</div>
<div class="mk-card__body">
<h3 class="mk-card__title">Slow mornings</h3>
<div class="mk-card__reveal">
<div class="mk-card__reveal-inner">
<p class="mk-card__cta mb-0">
<span class="mk-card__cta-text" aria-hidden="true">Read more</span>
</p>
</div>
</div>
</div>
</a>
<a class="mk-card" href="#">
<div class="mk-card__media">
<img src="/assets/img/everlasting.jpg" alt="A generated colour field" loading="lazy" decoding="async">
</div>
<div class="mk-card__body">
<h3 class="mk-card__title">Harbour light</h3>
<div class="mk-card__reveal">
<div class="mk-card__reveal-inner">
<p class="mk-card__cta mb-0">
<span class="mk-card__cta-text" aria-hidden="true">Read more</span>
</p>
</div>
</div>
</div>
</a>
<a class="mk-card" href="#">
<div class="mk-card__media">
<img src="/assets/img/everlasting.jpg" alt="A generated colour field" loading="lazy" decoding="async">
</div>
<div class="mk-card__body">
<h3 class="mk-card__title">Low tide</h3>
<div class="mk-card__reveal">
<div class="mk-card__reveal-inner">
<p class="mk-card__cta mb-0">
<span class="mk-card__cta-text" aria-hidden="true">Read more</span>
</p>
</div>
</div>
</div>
</a>
<a class="mk-card" href="#">
<div class="mk-card__media">
<img src="/assets/img/everlasting.jpg" alt="A generated colour field" loading="lazy" decoding="async">
</div>
<div class="mk-card__body">
<h3 class="mk-card__title">Long grass</h3>
<div class="mk-card__reveal">
<div class="mk-card__reveal-inner">
<p class="mk-card__cta mb-0">
<span class="mk-card__cta-text" aria-hidden="true">Read more</span>
</p>
</div>
</div>
</div>
</a>
</div>
<button class="mk-card-carousel__nav mk-card-carousel__nav--prev" type="button" data-rail-prev aria-label="Previous" hidden>
<i class="bi bi-chevron-left" aria-hidden="true"></i>
</button>
<button class="mk-card-carousel__nav mk-card-carousel__nav--next" type="button" data-rail-next aria-label="Next" hidden>
<i class="bi bi-chevron-right" aria-hidden="true"></i>
</button>
</section> id: cards-dark
surface: dark
label: Work
items: [4 items] | Field | Type | Notes |
|---|---|---|
surface |
text | empty (page), muted, subtle, primary, or dark |
label |
text | Names the scrollable region |
arrows |
boolean | Previous/next |
loop |
boolean | The track has no ends — past the last card comes the first again |
full_height |
boolean | The band fills the viewport when you scroll to it |
id |
text | Anchor id — also needed when a page carries more than one |
shape_bottom |
group | Cuts the band's BOTTOM edge. The shape is painted in this band's own ground and hangs over the band below, so the band below declares nothing. |
shape_top |
group | The same, on the band's TOP edge — it hangs upward over the band above. |
class_names |
text | |
items |
repeater |