Five landscape cards arranged in a CSS 3D carousel slider
Blog

How to Create a 3D Carousel Slider with HTML and CSS

Learn how to build a responsive 3D carousel slider with HTML and CSS. Native radio buttons select each slide, while CSS transforms arrange the cards in perspective. This version works without JavaScript and includes keyboard controls and reduced-motion support.

Quick answer: Add one radio input for each slide before the carousel stage. Use the :checked state and sibling selectors to move the selected card forward, then style the neighboring cards with rotateY() and translateZ().

What this CSS 3D carousel includes

The example displays five landscape cards in a 3D arc. Select a numbered control to bring a card forward. The artwork is embedded as SVG, so the live demo does not depend on external image servers.

How the 3D carousel works

Each radio input stores the selected slide. A selector such as #swc3d-slide-2:checked ~ .swc3d-carousel__stage .swc3d-slide-2 matches the active card. CSS changes its transform, opacity, and stacking order. The neighboring cards move to the sides and farther back. The carousel’s perspective makes those depth changes look three-dimensional.

Build the HTML structure

Place all radio inputs before the stage in the HTML. Give every input a unique ID and connect it to a numbered label with the matching for value. The downloadable example uses accessible inline SVG scenes. To use your own photos, replace each SVG with an <img> element and add concise, meaningful alt text.

Arrange slides with CSS transforms

Position each card at the center of the stage. For every selected radio, assign one card to the front, two to the right, and two to the left. Use translateX() for horizontal placement, translateZ() for depth, and rotateY() to angle the side cards. Update the selectors if you change the number of slides.

Make the carousel responsive

The stage uses a flexible height and each card keeps a landscape aspect ratio. At narrow widths, the cards widen and the side offsets shrink so the active slide remains readable. Adjust the stage height and card offsets to match your content column, then check the layout on a phone-sized screen.

Accessibility and reduced motion

Native radio controls work with the keyboard arrow keys. The numbered labels remain visible on touch screens, and a focus outline helps keyboard users see the active control. The carousel does not autoplay, so visitors decide when the content changes. A prefers-reduced-motion rule reduces transition movement for visitors who request less motion.

Customize the 3D image slider

  • Replace the sample SVG scenes with optimized WebP or AVIF images.
  • Change the card radius, border, shadow, and accent colors to fit your site.
  • Adjust perspective, rotateY(), and translateZ() to control the depth effect.
  • Keep IDs and radio group names unique when you add another carousel to the same page.

Common issues

The slides do not move

Check that every label points to the correct radio ID and that the inputs appear before the stage. CSS sibling selectors only match elements that follow the selected input.

The side cards are clipped

Check the stage and its parent containers for overflow: hidden. Allow visible overflow or reduce the side-card offsets at narrow widths.

Keyboard controls are missing

Keep the radio inputs focusable. Visually hide them with a clipped one-pixel style instead of using display: none.

Frequently asked questions

Can I build a 3D carousel with CSS only?

Yes. Radio buttons hold the selected state and CSS transforms arrange the slides. This works well for a small gallery with manual controls.

Does the carousel need JavaScript?

No. The demo uses HTML radio inputs and CSS selectors. JavaScript is useful for extra features such as autoplay, swipe gestures, or slides loaded from dynamic data.

Can I use my own images?

Yes. Replace each SVG with an image element, use descriptive alt text, and compress the files to fit the carousel dimensions.

Is it usable on mobile?

The numbered controls remain available without hover, and the radio group supports keyboard selection. Test the finished carousel with your theme at mobile widths.

Download the complete source

Try the live demo, then download the ZIP to inspect the standalone HTML and CSS files. The source includes five self-contained scenes, responsive slide positions, keyboard-operable controls, and reduced-motion support.

CSS 3D image carousel

Choose a number to rotate the gallery. Built with HTML and CSS; no JavaScript required.

HTML markup
<div class="swc3d-carousel">
  <input type="radio" name="slides" id="slide-1" checked>
  <input type="radio" name="slides" id="slide-2">
  <input type="radio" name="slides" id="slide-3">

  <div class="carousel__stage">
    <figure class="slide slide-1">Slide one</figure>
    <figure class="slide slide-2">Slide two</figure>
    <figure class="slide slide-3">Slide three</figure>
  </div>

  <div class="carousel__controls">
    <label for="slide-1">1</label>
    <label for="slide-2">2</label>
    <label for="slide-3">3</label>
  </div>
</div>
CSS transforms
.carousel {
  perspective: 1000px;
}

.carousel__stage {
  position: relative;
  height: 340px;
  transform-style: preserve-3d;
}

.slide {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) translateZ(-300px);
  transition: transform 600ms ease, opacity 600ms ease;
}

#slide-1:checked ~ .carousel__stage .slide-1 {
  z-index: 2;
  opacity: 1;
  transform: translate(-50%, -50%) translateZ(0) rotateY(0);
}

#slide-1:checked ~ .carousel__stage .slide-2 {
  transform: translate(10%, -50%) translateZ(-120px) rotateY(-25deg);
}

@media (max-width: 600px) {
  .carousel__stage { height: 270px; }
}