Cards & galleries
Flip card
Pure CSSHover, tap or focus to flip. The back face is hidden until it turns toward you.
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));
}
}