A four sided cube rolls forward a face at a time and pauses on each one, so it can cycle words, stats or logos. Faces sit at rotateX(90deg times --i) and translateZ half the cube.
Also known as: css 3d cube animation, rotating cube css, cube flip text animation.
<div class="kfa-cube-rotate"><div class="kfa-cube-rotate-cube"><span style="--i: 0">One</span><span style="--i: 1">Two</span><span style="--i: 2">Three</span><span style="--i: 3">Four</span><i class="kfa-cube-rotate-cap"></i><i class="kfa-cube-rotate-cap"></i></div></div>
.kfa-cube-rotate {
--c: var(--kfa-color, #3b82f6);
font-size: var(--kfa-size, 16px);
width: 5em;
height: 5em;
perspective: 24em;
}
.kfa-cube-rotate-cube {
position: relative;
height: 100%;
transform-style: preserve-3d;
animation: kfa-cube-rotate-kf 6s cubic-bezier(0.65, 0, 0.3, 1.15) infinite;
}
.kfa-cube-rotate-cube > span {
position: absolute;
inset: 0;
display: grid;
place-items: center;
border-radius: 0.3em;
background: var(--c);
color: #fff;
font-family: system-ui, sans-serif;
font-weight: 700;
transform: rotateX(calc(var(--i) * 90deg)) translateZ(2.5em);
backface-visibility: hidden;
}
/* every other face a shade darker, so the edge reads while it turns */
.kfa-cube-rotate-cube > span:nth-child(even) {
background: color-mix(in srgb, var(--c) 72%, #000);
}
/* the two square ends; they spin in their own plane as the cube rolls */
.kfa-cube-rotate-cap {
position: absolute;
inset: 0;
border-radius: 0.3em;
background: color-mix(in srgb, var(--c) 58%, #000);
transform: rotateY(90deg) translateZ(2.5em);
}
.kfa-cube-rotate-cap + .kfa-cube-rotate-cap {
transform: rotateY(-90deg) translateZ(2.5em);
}
/* translateZ(-2.5em) keeps the front face near its real size; rotateY(-22deg) shows an end */
@keyframes kfa-cube-rotate-kf {
0%, 18% { transform: translateZ(-2.5em) rotateY(-22deg) rotateX(0); }
25%, 43% { transform: translateZ(-2.5em) rotateY(-22deg) rotateX(-90deg); }
50%, 68% { transform: translateZ(-2.5em) rotateY(-22deg) rotateX(-180deg); }
75%, 93% { transform: translateZ(-2.5em) rotateY(-22deg) rotateX(-270deg); }
100% { transform: translateZ(-2.5em) rotateY(-22deg) rotateX(-360deg); }
}
@media (prefers-reduced-motion: reduce) {
.kfa-cube-rotate, .kfa-cube-rotate *, .kfa-cube-rotate::before, .kfa-cube-rotate::after, .kfa-cube-rotate *::before, .kfa-cube-rotate *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--kfa-color on the element or a parent.
Currently previewing #3b82f6.--kfa-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.