<input type="checkbox" id="debug" />

<ul class="cards" id="cards">
    <li id="card_0">
        <img src="https://assets.codepen.io/89905/coverflow--Front-1024x1024.jpg" width="1200" height="1200" />
    </li>
    <li id="card_1">
        <img src="https://assets.codepen.io/89905/coverflow--A-Thousand-Clouds-Front-Cover-1024x1024.jpg" width="1200" height="1200" />
    </li>
    <li id="card_2">
        <img src="https://assets.codepen.io/89905/coverflow--Odd-World-EP-SMALL-1024x1024.png" width="1200" height="1200" />
    </li>
    <li id="card_3">
        <img src="https://assets.codepen.io/89905/coverflow--Forest-Blue-Pre-LR-1024x1024.png" width="1200" height="1200" />
    </li>
    <li id="card_4">
        <img src="https://assets.codepen.io/89905/coverflow--MOM-Remixes-1024x1024.jpg" width="1200" height="1200" />
    </li>
    <li id="card_5">
        <img src="https://assets.codepen.io/89905/coverflow--ALONE-TOGETHER-remix-V71-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_6">
        <img src="https://assets.codepen.io/89905/coverflow--Nature-Therapy-Pre-LR-550x550.png" width="1200" height="1200" />
    </li>
    <li id="card_7">
        <img src="https://assets.codepen.io/89905/coverflow--Deep-Dive-Ambient-Edits-V8-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_8">
        <img src="https://assets.codepen.io/89905/coverflow--Alpine-Koresma-x-Aroth-Artwork-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_9">
        <img src="https://assets.codepen.io/89905/coverflow--Out-Of-the-Dark-Cover-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_11">
        <img src="https://assets.codepen.io/89905/coverflow--2020-06-07-Marley-Carroll-Single-Blue-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_12">
        <img src="https://assets.codepen.io/89905/coverflow--Deep-Dive-EP-Cover-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_13">
        <img src="https://assets.codepen.io/89905/coverflow--Blackrose-Cover-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_14">
        <img src="https://assets.codepen.io/89905/coverflow--FW-Imagine-Gold-Remixes2-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_15">
        <img src="https://assets.codepen.io/89905/coverflow--We-Are-COVER-MAIN-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_16">
        <img src="https://assets.codepen.io/89905/coverflow--Bath-House-Flat-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_17">
        <img src="https://assets.codepen.io/89905/coverflow--Pronoia-JPG-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_18">
        <img src="https://assets.codepen.io/89905/coverflow--Lapa9Theory-Cracking-Stores-no-Loci-logo-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_19">
        <img src="https://assets.codepen.io/89905/coverflow--EMANCIPATOR_MOM_AlbumCover-2000px-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_20">
        <img src="https://assets.codepen.io/89905/coverflow--MURGE-ep-cvr-3000x3000-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_21">
        <img src="https://assets.codepen.io/89905/coverflow--Emancipator_Laybrinth-ART-01-4000x4000-at-300dpi-550x550.jpg" width="1200" height="1200" />
    </li>
    <li id="card_22">
        <img src="https://assets.codepen.io/89905/coverflow--cover-550x550.jpg" width="1200" height="1200" />
    </li>
</ul>

<div class="warning">⚠️ Your browser does not support CSS Scroll-Linked Animations, so this demo won't work. If you're feeling adventurous use Chrome 89 with “Experimental Web Platform Features” enabled. Alternatively you can <a href="https://twitter.com/bramus/status/1357391991114502144" target="_top" rel="noopener noreferrer">check out a recording of this demo</a></div>
/*
  This is a JS based version of https://codepen.io/bramus/pen/xxRZZdK
  It uses polyfills for css-typed-om and scroll-timeline

  While it has some bugs on its own (it's not performant), it does render
  the scroll timeline correctly. See bug 1 in CSS version for a description.
*/

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

:root {
  --cover-size: 15rem;
}

@media (max-width: 800px) {
	:root {
  		--cover-size: 9rem;
	}
}

body {
  background: #111;
  min-height: 100vh;
  font-family: sans-serif;

  display: flex;
  place-items: center;
}

.cards {
  list-style: none;
  overflow: scroll;
  width: 100%;
  white-space: nowrap;

  scroll-snap-type: x mandatory;
  outline: 1px solid #333;
  background: rgba(0 0 0 / 0.5);
}

.cards li {
  display: inline-block;
  width: var(--cover-size);
  height: var(--cover-size);
  scroll-snap-align: center;
}

.cards li img {
  dislay: block;
  width: var(--cover-size);
  height: var(--cover-size);
	
  -webkit-box-reflect: below 0.5em linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0.25));
}

.cards {
  max-width: calc(var(--cover-size) * 6);
  margin: 0 auto;
  padding: calc(var(--cover-size) / 3 * 2) calc(50% - (var(--cover-size) / 3 * 2));
}

/* Show warning for older browser */
.warning {
  position: fixed;
  bottom: 1em;
  right: 1em;
  left: 1em;
  padding: 1em;
  border: 1px solid black;
  z-index: 9999;
  text-align: center;
  color: black;
  background: rgba(255 255 225 / 0.9);
	display: none;
}

.warning a {
  color: blue;
}

#debug {
  position: absolute;
  top: 1em;
  left: 1em;
}
#debug::after {
  content: " Show Debug";
  margin-left: 1.5em;
  color: white;
  white-space: nowrap;
}

#debug:checked + .cards {
  border: 1px solid lime;
}

#debug:checked + .cards li {
  text-align: center;
  color: white;
  border: 1px solid blue;
}

#debug:checked + .cards li::before {
  content: attr(id);
  display: block;
  position: absolute;
  inset: 0;
  line-height: var(--cover-size);
  opacity: 0.5;
}

#debug:checked + .cards li img {
  opacity: 0.5;
}
import { showDialog } from 'https://codepen.io/bramus/pen/ZEqMOLz/cccfe67c2b9cdfbeb5fb59083dbd0a64.js';
showDialog('https://scroll-driven-animations.style/demos/cover-flow/css/');

// Alternative Versions:
// - JS ScrollTimeline 2022: https://codepen.io/bramus/pen/MWVExQg
// - JS Motion One: https://codepen.io/bramus/pen/PoRKEaZ 
// - CSS @scroll-timeline 2021: https://codepen.io/bramus/pen/xxRZZdK
// - JS ScrollTimeline 2021: https://codepen.io/bramus/pen/PobZbBV 👈 = The version you are currently looking at

// Polyfill for browsers with no Scroll-Timeline support
import 'https://rawcdn.githack.com/flackr/scroll-timeline/3063e156535f3ab1ffc8a4000ffdd3290232c121/dist/scroll-timeline.js';

const $ul = document.querySelector('ul');
const $lis = document.querySelectorAll('ul > li');

$lis.forEach(($li) => {

	$li.style.perspective = '40em';
	$li.style.position = 'relative';

	// Create ScrollTimeline
	const scrollTimeline = new ScrollTimeline({
		scrollSource: $ul,
		timeRange: 1,
		orientation: 'inline',
		fill: 'both',
		scrollOffsets: [
			{ target: $li, edge: 'end', threshold: 0 },
			{ target: $li, edge: 'start', threshold: 0 },
		],
	});

	// Animate <li>
	new Animation(
		new KeyframeEffect(
			$li,
			{
				zIndex: ["1", "100", "1000", "100", "1"],
			},
			{ duration: 1, fill: "both" }
		),
		scrollTimeline
	).play();

	// Animate nested <img>
	new Animation(
		new KeyframeEffect(
			$li.querySelector('img'),
			{
				transform: [
					'rotateY(-45deg) translateX(-100%)',
					'rotateY(-45deg) translateX(0)',
					'rotateY(0deg) translateZ(1em) scale(1.5)',
					'rotateY(45deg) translateX(0)',
					'rotateY(45deg) translateX(100%)',
				],
			},
			{ duration: 1, fill: "both" }
		),
		scrollTimeline
	).play();

});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.