22 CSS Image Carousels12 / 22

Pure CSSMIT licensed

Vertical Image Carousel

A carousel that scrolls up and down instead of left to right — ideal for sidebar widgets, story-style feeds and creative portfolios. Vertical scroll-snap locks each frame into view; a captioned overlay rides along with every image.

Published

Live Demo
Try it

The code

<section class="car-12" aria-label="Vertical image carousel">
  <ul class="car-12__scroller" tabindex="0" role="group" aria-label="Gallery, scroll up and down">
    <li class="car-12__frame"><img src="https://picsum.photos/seed/vert-1/700/900" width="700" height="900" alt="Desert dunes at sunset"><span class="car-12__cap">Sahara, Morocco</span></li>
    <li class="car-12__frame"><img src="https://picsum.photos/seed/vert-2/700/900" width="700" height="900" alt="Glacier lagoon"><span class="car-12__cap">Jökulsárlón, Iceland</span></li>
    <li class="car-12__frame"><img src="https://picsum.photos/seed/vert-3/700/900" width="700" height="900" alt="Terraced rice fields"><span class="car-12__cap">Bali, Indonesia</span></li>
    <li class="car-12__frame"><img src="https://picsum.photos/seed/vert-4/700/900" width="700" height="900" alt="Autumn forest path"><span class="car-12__cap">Kyoto, Japan</span></li>
  </ul>
</section>
.car-12,
.car-12 *,
.car-12 *::before,
.car-12 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.car-12 ::selection {
  background: #0f766e;
  color: #fff;
}

.car-12 {
  font-family: 'Segoe UI',system-ui,sans-serif;
  width: 100%;
  min-height: 100vh;
  padding: 40px 20px;
  background: #0e1513;
  display: flex;
  align-items: center;
  justify-content: center;
}

.car-12__scroller {
  list-style: none;
  width: min(340px,100%);
  height: min(560px,80vh);
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  overscroll-behavior: contain;
  border-radius: 20px;
  box-shadow: 0 30px 60px -34px rgba(0,0,0,.9);
  scrollbar-width: none;
}

.car-12__scroller::-webkit-scrollbar {
  display: none;
}

.car-12__scroller:focus-visible {
  outline: 3px solid #2dd4bf;
  outline-offset: 3px;
}

.car-12__frame {
  position: relative;
  height: 100%;
  scroll-snap-align: start;
  overflow: hidden;
}

.car-12__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.car-12__cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 40px 20px 20px;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  letter-spacing: .01em;
  background: linear-gradient(transparent,rgba(6,10,9,.85));
}

@media (prefers-reduced-motion: reduce) {
  .car-12__scroller {
    scroll-behavior: auto;
  }
}
/* No JavaScript — vertical scroll-snap (y mandatory) with a fixed-height, focusable, keyboard-scrollable window. */
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 Image Carousel 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: Vertical Image Carousel
Source: https://codefronts.com/snippets/css-image-carousel/vertical-image-carousel/

A carousel that scrolls up and down instead of left to right — ideal for sidebar widgets, story-style feeds and creative portfolios. Vertical scroll-snap locks each frame into view; a captioned overlay rides along with every image.
## HTML
```html
<section class="car-12" aria-label="Vertical image carousel">
  <ul class="car-12__scroller" tabindex="0" role="group" aria-label="Gallery, scroll up and down">
    <li class="car-12__frame"><img src="https://picsum.photos/seed/vert-1/700/900" width="700" height="900" alt="Desert dunes at sunset"><span class="car-12__cap">Sahara, Morocco</span></li>
    <li class="car-12__frame"><img src="https://picsum.photos/seed/vert-2/700/900" width="700" height="900" alt="Glacier lagoon"><span class="car-12__cap">Jökulsárlón, Iceland</span></li>
    <li class="car-12__frame"><img src="https://picsum.photos/seed/vert-3/700/900" width="700" height="900" alt="Terraced rice fields"><span class="car-12__cap">Bali, Indonesia</span></li>
    <li class="car-12__frame"><img src="https://picsum.photos/seed/vert-4/700/900" width="700" height="900" alt="Autumn forest path"><span class="car-12__cap">Kyoto, Japan</span></li>
  </ul>
</section>
```
## CSS
```css
.car-12,
.car-12 *,
.car-12 *::before,
.car-12 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.car-12 ::selection {
  background: #0f766e;
  color: #fff;
}

.car-12 {
  font-family: 'Segoe UI',system-ui,sans-serif;
  width: 100%;
  min-height: 100vh;
  padding: 40px 20px;
  background: #0e1513;
  display: flex;
  align-items: center;
  justify-content: center;
}

.car-12__scroller {
  list-style: none;
  width: min(340px,100%);
  height: min(560px,80vh);
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  overscroll-behavior: contain;
  border-radius: 20px;
  box-shadow: 0 30px 60px -34px rgba(0,0,0,.9);
  scrollbar-width: none;
}

.car-12__scroller::-webkit-scrollbar {
  display: none;
}

.car-12__scroller:focus-visible {
  outline: 3px solid #2dd4bf;
  outline-offset: 3px;
}

.car-12__frame {
  position: relative;
  height: 100%;
  scroll-snap-align: start;
  overflow: hidden;
}

.car-12__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.car-12__cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 40px 20px 20px;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  letter-spacing: .01em;
  background: linear-gradient(transparent,rgba(6,10,9,.85));
}

@media (prefers-reduced-motion: reduce) {
  .car-12__scroller {
    scroll-behavior: auto;
  }
}
```

## JavaScript
```js
/* No JavaScript — vertical scroll-snap (y mandatory) with a fixed-height, focusable, keyboard-scrollable window. */
```

How this works

The scroller uses scroll-snap-type:y mandatory with a fixed height, so each full-height frame (scroll-snap-align:start) snaps into place as you scroll vertically. Frames are aspect-locked and the images use object-fit:cover, so nothing shifts as media loads.

The scroller is focusable and responds to Up/Down and Page keys. Each caption is real text over a gradient scrim, kept legible and indexable, not baked into pixels.

Make it yours

  • Set how tall the visible window is via the scroller height.
  • Switch to proximity snapping for a looser vertical feel.
  • Add per-frame entrance motion with scroll-driven animations where supported.
  • Move the caption to the top or make it a side rail.

Gotchas — read before shipping

  • Give the scroller an explicit height, or vertical snapping has nothing to snap within.
  • Use overscroll-behavior:contain so scrolling the widget doesn't chain to the page.
  • Ensure each frame is at least the scroller's height so one snaps fully at a time.

Browser support

ChromeSafariFirefoxEdge
69+11+68+69+

Vertical scroll-snap is as well supported as horizontal; overscroll-behavior is widely available.

Techniques used in this demo

Search CodeFronts

Loading…