Hover card fan
Pure CSSThree overlapping cards: the one you point at straightens and comes toward you while the others dim and lean away. Static strips catch the pointer, so nothing flickers.
Cover and pages hinge on the spine, each opening to a slightly different angle.
Your edited version
transform-origin: left — the spine is the hinge.--n. A 1px translateZ per sheet stops them z-fighting.var(--end), computed per sheet, so one animation fans the pages out.animation-delay makes the cover lead and the pages follow.transform-origin: leftvar() end angle in @keyframesstaggered delays<div class="scene">
<div class="book">
<i style="--n:0"></i>
<i style="--n:1"></i>
<i style="--n:2"></i>
<i style="--n:3"></i>
<i style="--n:4" class="cover"></i>
</div>
</div>
.scene {
perspective: 1000px;
}
.book {
position: relative;
width: 130px;
height: 175px;
border-radius: 2px 8px 8px 2px;
background: #4a3a99; /* back cover */
transform-style: preserve-3d;
transform: translateX(60px) rotateX(24deg) rotateY(-12deg);
}
.book i {
--end: calc(-118deg - var(--n) * 12deg);
position: absolute;
inset: 3px 3px 3px 0;
border-radius: 0 5px 5px 0;
background: linear-gradient(90deg, #cfd3e6, #fff 14%);
transform-origin: left center;
transform: translateZ(calc(var(--n) * 1px));
animation: open 3.6s ease-in-out infinite alternate;
animation-delay: calc((4 - var(--n)) * 0.14s);
}
.book .cover {
inset: 0;
border-radius: 2px 8px 8px 2px;
background: linear-gradient(90deg, #4a3a99, #8b6cff 12%);
}
@keyframes open {
0%, 10% { transform: translateZ(calc(var(--n) * 1px)) rotateY(0deg); }
90%, 100% { transform: translateZ(calc(var(--n) * 1px)) rotateY(var(--end)); }
}
.d-book {
position: relative;
width: 104px;
height: 140px;
transform-style: preserve-3d;
transform: translateX(46px) rotateX(24deg) rotateY(-12deg);
// back cover
background: color-mix(in srgb, var(--accent) 70%, #000);
border-radius: 2px 8px 8px 2px;
// Pages then cover (last <i>), all hinged on the spine. --n is 0…4 from the markup.
i {
position: absolute;
inset: 3px 3px 3px 0;
border-radius: 0 5px 5px 0;
background: linear-gradient(90deg, #cfd3e6, #fff 14%);
transform-origin: left center;
// Later sheets sit higher and open further.
--end: calc(-118deg - var(--n) * 12deg);
transform: translateZ(calc(var(--n) * 1px));
animation: d-book-open 3.6s ease-in-out infinite alternate;
animation-delay: calc((4 - var(--n)) * 0.14s);
}
i:last-of-type {
inset: 0;
border-radius: 2px 8px 8px 2px;
background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 60%, #000), var(--accent) 12%);
}
// title, stamped on the inside back so it shows once the book is open
b {
position: absolute;
inset: 0;
display: grid;
place-items: center;
color: #fff;
font-size: 20px;
line-height: 1.1;
text-align: center;
}
}
@keyframes d-book-open {
0%,
10% {
transform: translateZ(calc(var(--n) * 1px)) rotateY(0deg);
}
90%,
100% {
transform: translateZ(calc(var(--n) * 1px)) rotateY(var(--end));
}
}