Pure TailwindMIT licensed

Tailwind Full-Screen Hero Slideshow with Auto Cross-Fade

A high-impact auto-advancing hero that cross-fades full-bleed photography under a headline. One shared keyframe plus a negative animation-delay per slide is the entire timeline — no setInterval to leak, desync or keep alive in a background tab.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="tcar-05 w-full min-h-svh font-tcar05-sans" aria-label="Featured highlights slideshow" aria-roledescription="carousel">
  <div class="group relative h-svh min-h-[520px] overflow-hidden bg-tcar05-ink">
    <div class="absolute inset-0 opacity-0 animate-tcar05-fade group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none motion-reduce:opacity-100">
      <img src="https://picsum.photos/seed/hero-peaks/1600/900" width="1600" height="900" fetchpriority="high" decoding="async" alt="Mist over mountain peaks at dawn" class="size-full object-cover block">
    </div>
    <div class="absolute inset-0 opacity-0 animate-tcar05-fade [animation-delay:-5s] group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none">
      <img src="https://picsum.photos/seed/hero-coast/1600/900" width="1600" height="900" loading="lazy" decoding="async" alt="Rugged coastline at golden hour" class="size-full object-cover block">
    </div>
    <div class="absolute inset-0 opacity-0 animate-tcar05-fade [animation-delay:-10s] group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none">
      <img src="https://picsum.photos/seed/hero-forest/1600/900" width="1600" height="900" loading="lazy" decoding="async" alt="Sun beams through a pine forest" class="size-full object-cover block">
    </div>
    <div aria-hidden="true" class="absolute inset-0 z-[1] bg-[linear-gradient(90deg,oklch(0.15_0.01_265/0.82),oklch(0.15_0.01_265/0.25)_60%,transparent)]"></div>
    <div class="absolute left-0 bottom-0 z-[2] p-[clamp(28px,6vw,72px)] max-w-[640px] text-white">
      <p class="text-[13px] tracking-[0.24em] uppercase mb-3.5 m-0">New Season</p>
      <h2 class="text-[clamp(38px,7vw,72px)] leading-[1.02] font-black tracking-[-0.02em] m-0 [text-shadow:0_2px_30px_oklch(0_0_0/0.45)]">Go further,<br>pack lighter</h2>
      <a href="#" class="inline-flex items-center min-h-11 mt-6 px-7 rounded-full bg-white text-tcar05-ink font-bold text-sm no-underline transition-[translate,box-shadow] duration-200 hover:-translate-y-0.5 hover:shadow-[0_14px_30px_-14px_oklch(0_0_0/0.6)] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] motion-reduce:transition-none motion-reduce:hover:translate-y-0">Explore the collection</a>
    </div>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tcar05-ink: #0d0f12;
  --color-tcar05-ink: oklch(0.16 0.008 265);
  --font-tcar05-sans: 'Archivo', system-ui, sans-serif;
  --animate-tcar05-fade: tcar05-fade 15s ease-in-out infinite;
}

@keyframes tcar05-fade {
  0% {
    opacity: 0;
  }

  5% {
    opacity: 1;
  }

  28% {
    opacity: 1;
  }

  33% {
    opacity: 0;
  }

  100% {
    opacity: 0;
  }
}

.tcar-05 {
  width: 100%;
  min-height: 100svh;
}

.tcar-05 ::selection {
  background: #fff;
  color: #111;
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<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.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-tcar05-ink: #0d0f12;
  --color-tcar05-ink: oklch(0.16 0.008 265);
  --font-tcar05-sans: 'Archivo', system-ui, sans-serif;
  --animate-tcar05-fade: tcar05-fade 15s ease-in-out infinite;
}

@keyframes tcar05-fade {
  0% {
    opacity: 0;
  }

  5% {
    opacity: 1;
  }

  28% {
    opacity: 1;
  }

  33% {
    opacity: 0;
  }

  100% {
    opacity: 0;
  }
}

.tcar-05 {
  width: 100%;
  min-height: 100svh;
}

.tcar-05 ::selection {
  background: #fff;
  color: #111;
}
3Fonts used by this demooptional — skip if you have your own type stack
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Archivo:wght@400;600;700;800;900&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • Three slides, one @theme animation token and two arbitrary [animation-delay:] values. The CSS version needed a :nth-child rule per slide to say the same thing.
  • The overlay scrim moved from a ::after pseudo-element to a real div. A pseudo-element would have needed after:content-[''] plus an arbitrary gradient on every slide; one element is less markup and easier to retune.
  • UI change from the CSS original: the scrim's dark stop went from rgba(8,10,14,.72) to oklch(0.15 0.01 265 / 0.82), and the CTA gained min-h-11. The original headline measured 3.9:1 against the brightest of the three photographs; it now clears 4.5:1 on all three.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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 Full-Screen Hero Slideshow with Auto Cross-Fade
Source: https://codefronts.com/snippets/tailwind-css-image-carousel/tailwind-full-screen-hero-slideshow-cross-fade/

A high-impact auto-advancing hero that cross-fades full-bleed photography under a headline. One shared keyframe plus a negative animation-delay per slide is the entire timeline — no setInterval to leak, desync or keep alive in a background tab.
## HTML
```html
<section class="tcar-05 w-full min-h-svh font-tcar05-sans" aria-label="Featured highlights slideshow" aria-roledescription="carousel">
  <div class="group relative h-svh min-h-[520px] overflow-hidden bg-tcar05-ink">
    <div class="absolute inset-0 opacity-0 animate-tcar05-fade group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none motion-reduce:opacity-100">
      <img src="https://picsum.photos/seed/hero-peaks/1600/900" width="1600" height="900" fetchpriority="high" decoding="async" alt="Mist over mountain peaks at dawn" class="size-full object-cover block">
    </div>
    <div class="absolute inset-0 opacity-0 animate-tcar05-fade [animation-delay:-5s] group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none">
      <img src="https://picsum.photos/seed/hero-coast/1600/900" width="1600" height="900" loading="lazy" decoding="async" alt="Rugged coastline at golden hour" class="size-full object-cover block">
    </div>
    <div class="absolute inset-0 opacity-0 animate-tcar05-fade [animation-delay:-10s] group-hover:[animation-play-state:paused] group-focus-within:[animation-play-state:paused] motion-reduce:animate-none">
      <img src="https://picsum.photos/seed/hero-forest/1600/900" width="1600" height="900" loading="lazy" decoding="async" alt="Sun beams through a pine forest" class="size-full object-cover block">
    </div>
    <div aria-hidden="true" class="absolute inset-0 z-[1] bg-[linear-gradient(90deg,oklch(0.15_0.01_265/0.82),oklch(0.15_0.01_265/0.25)_60%,transparent)]"></div>
    <div class="absolute left-0 bottom-0 z-[2] p-[clamp(28px,6vw,72px)] max-w-[640px] text-white">
      <p class="text-[13px] tracking-[0.24em] uppercase mb-3.5 m-0">New Season</p>
      <h2 class="text-[clamp(38px,7vw,72px)] leading-[1.02] font-black tracking-[-0.02em] m-0 [text-shadow:0_2px_30px_oklch(0_0_0/0.45)]">Go further,<br>pack lighter</h2>
      <a href="#" class="inline-flex items-center min-h-11 mt-6 px-7 rounded-full bg-white text-tcar05-ink font-bold text-sm no-underline transition-[translate,box-shadow] duration-200 hover:-translate-y-0.5 hover:shadow-[0_14px_30px_-14px_oklch(0_0_0/0.6)] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] motion-reduce:transition-none motion-reduce:hover:translate-y-0">Explore the collection</a>
    </div>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tcar05-ink: #0d0f12;
  --color-tcar05-ink: oklch(0.16 0.008 265);
  --font-tcar05-sans: 'Archivo', system-ui, sans-serif;
  --animate-tcar05-fade: tcar05-fade 15s ease-in-out infinite;
}

@keyframes tcar05-fade {
  0% {
    opacity: 0;
  }

  5% {
    opacity: 1;
  }

  28% {
    opacity: 1;
  }

  33% {
    opacity: 0;
  }

  100% {
    opacity: 0;
  }
}

.tcar-05 {
  width: 100%;
  min-height: 100svh;
}

.tcar-05 ::selection {
  background: #fff;
  color: #111;
}
```

How this works

The timeline is three numbers. Every slide runs the same 15s opacity keyframe; slides two and three start it 5s and 10s in the past. The result is a perfectly even hand-off with one keyframe and no scheduler. Only opacity animates, so the whole hero stays on the compositor.

Pause is a group variant. The deck is the group; each slide carries group-hover:[animation-play-state:paused]. The user can stop on an image, which an autoplaying hero must allow.

The scrim is a utility, not a pseudo-element. A single absolutely-positioned div with a gradient background sits above the images and below the copy — easier to tune than the original's ::after, and it keeps the headline above 4.5:1 on all three photographs.

Make it yours

  • Cycle length: the 15s in --animate-tcar05-fade, kept in step with the keyframe stops.
  • Add a slide: one more layer plus [animation-delay:-Xs] where X = duration ÷ count × index.
  • Ken Burns: add a small scale to the keyframe — still compositor-only.
  • Headline block: pure layout utilities, independent of the timeline.

Gotchas — read before shipping

  • Delays must be evenly spaced (duration ÷ N) or slides overlap and gap. This is arithmetic the utility cannot check for you.
  • Keep the scrim. Text over uncontrolled photography fails contrast on at least one slide, every time.
  • min-h-svh, not min-h-screen: on mobile 100vh is measured against the collapsed URL bar and crops the hero.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

Staggered opacity keyframes need nothing modern; the floor quoted is Tailwind v4's generated sheet. svh units are Baseline since Safari 15.4.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Plain CSSno Tailwind surface

Search CodeFronts

Loading…