3D equalizer
Pure CSSSeven real cuboids bouncing like an audio meter. Walls are squashed with scaleY and each lid rides down by the same amount, so nothing but transforms ever changes.
The classic square loader: half a turn on X, then half a turn on Y.
Your edited version
perspective() function goes inside the transform itself.perspective.perspective() inside transformmulti-step @keyframesno wrapper needed<div class="loader"></div>
.loader {
width: 90px;
height: 90px;
border-radius: 12px;
background: linear-gradient(135deg, #2ee6d6, #8b6cff);
box-shadow: 0 0 30px rgb(139 108 255 / 0.6);
animation: flip 1.8s ease-in-out infinite;
}
@keyframes flip {
0% { transform: perspective(260px) rotateX(0deg) rotateY(0deg); }
50% { transform: perspective(260px) rotateX(-180deg) rotateY(0deg); }
100% { transform: perspective(260px) rotateX(-180deg) rotateY(-180deg); }
}
.d-flipper {
width: 76px;
height: 76px;
border-radius: 10px;
background: linear-gradient(135deg, var(--accent-2), var(--accent));
box-shadow: 0 0 30px color-mix(in srgb, var(--accent) 60%, transparent);
animation: d-flipper 1.8s ease-in-out infinite;
}
// perspective() INSIDE the transform: a self-contained 3D element, no parent needed.
@keyframes d-flipper {
0% {
transform: perspective(240px) rotateX(0deg) rotateY(0deg);
}
50% {
transform: perspective(240px) rotateX(-180deg) rotateY(0deg);
}
100% {
transform: perspective(240px) rotateX(-180deg) rotateY(-180deg);
}
}