25 CSS Text Animations 10 / 25
CSS 3D Text Flip Animation
Words rotate in 3D on the Y-axis using CSS perspective and backface-visibility to flip between two text faces like a rotating sign.
The code
<div class="ta-10">
<div class="ta-10__stage">
<p class="ta-10__label">Rotating between</p>
<div class="ta-10__scene">
<div class="ta-10__flipper">
<div class="ta-10__face ta-10__face--front">Design</div>
<div class="ta-10__face ta-10__face--back">Motion</div>
</div>
</div>
<p class="ta-10__sub">perspective · rotateY · backface-visibility</p>
</div>
</div> <div class="ta-10">
<div class="ta-10__stage">
<p class="ta-10__label">Rotating between</p>
<div class="ta-10__scene">
<div class="ta-10__flipper">
<div class="ta-10__face ta-10__face--front">Design</div>
<div class="ta-10__face ta-10__face--back">Motion</div>
</div>
</div>
<p class="ta-10__sub">perspective · rotateY · backface-visibility</p>
</div>
</div>.ta-10, .ta-10 *, .ta-10 *::before, .ta-10 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-10 ::selection { background: #0f766e; color: #fff; }
.ta-10 {
--bg: #05120f;
--teal: #2dd4bf;
--gold: #fbbf24;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Syne', 'Helvetica Neue', sans-serif;
}
.ta-10__stage { text-align: center; }
.ta-10__label {
font-size: 0.72rem;
color: #1f4040;
letter-spacing: 0.15em;
text-transform: uppercase;
margin-bottom: 0.5rem;
}
.ta-10__scene {
perspective: 600px;
display: inline-block;
height: clamp(3rem, 9vw, 5.5rem);
overflow: visible;
}
.ta-10__flipper {
position: relative;
transform-style: preserve-3d;
animation: ta-10-flip 4s ease-in-out infinite;
height: 100%;
display: flex;
align-items: center;
}
.ta-10__face {
font-size: clamp(2.5rem, 8vw, 5rem);
font-weight: 900;
position: absolute;
width: 100%;
text-align: center;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
letter-spacing: -0.02em;
white-space: nowrap;
}
.ta-10__face--front { color: var(--teal); }
.ta-10__face--back { color: var(--gold); transform: rotateY(180deg); }
.ta-10__sub {
font-size: 0.65rem;
color: #1a3030;
margin-top: 1rem;
letter-spacing: 0.08em;
font-family: 'Courier New', monospace;
}
@keyframes ta-10-flip {
0% { transform: rotateY(0deg); }
35% { transform: rotateY(0deg); }
50% { transform: rotateY(-180deg); }
85% { transform: rotateY(-180deg); }
100% { transform: rotateY(-360deg); }
}
@media (prefers-reduced-motion: reduce) {
.ta-10__flipper { animation: none; }
.ta-10__face--back { display: none; }
} .ta-10, .ta-10 *, .ta-10 *::before, .ta-10 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-10 ::selection { background: #0f766e; color: #fff; }
.ta-10 {
--bg: #05120f;
--teal: #2dd4bf;
--gold: #fbbf24;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Syne', 'Helvetica Neue', sans-serif;
}
.ta-10__stage { text-align: center; }
.ta-10__label {
font-size: 0.72rem;
color: #1f4040;
letter-spacing: 0.15em;
text-transform: uppercase;
margin-bottom: 0.5rem;
}
.ta-10__scene {
perspective: 600px;
display: inline-block;
height: clamp(3rem, 9vw, 5.5rem);
overflow: visible;
}
.ta-10__flipper {
position: relative;
transform-style: preserve-3d;
animation: ta-10-flip 4s ease-in-out infinite;
height: 100%;
display: flex;
align-items: center;
}
.ta-10__face {
font-size: clamp(2.5rem, 8vw, 5rem);
font-weight: 900;
position: absolute;
width: 100%;
text-align: center;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
letter-spacing: -0.02em;
white-space: nowrap;
}
.ta-10__face--front { color: var(--teal); }
.ta-10__face--back { color: var(--gold); transform: rotateY(180deg); }
.ta-10__sub {
font-size: 0.65rem;
color: #1a3030;
margin-top: 1rem;
letter-spacing: 0.08em;
font-family: 'Courier New', monospace;
}
@keyframes ta-10-flip {
0% { transform: rotateY(0deg); }
35% { transform: rotateY(0deg); }
50% { transform: rotateY(-180deg); }
85% { transform: rotateY(-180deg); }
100% { transform: rotateY(-360deg); }
}
@media (prefers-reduced-motion: reduce) {
.ta-10__flipper { animation: none; }
.ta-10__face--back { display: none; }
}How this works
The flip container establishes a 3D rendering context with perspective: 600px on the parent and transform-style: preserve-3d on the flipping element. Two text faces — front and back — are both position: absolute and full-size, with the back face pre-rotated rotateY(180deg) so it starts facing away. backface-visibility: hidden on each face ensures only the forward-facing surface is visible at any rotation angle.
The ta-10-flip keyframe rotates the container from 0deg to -180deg then continues to -360deg, completing a full revolution. As the rotation passes 90° the front face disappears and the back face becomes visible, creating the card-flip illusion. Looping the animation with a hold pause (0–40% static, 50–60% flipping, 60–100% static on new face) makes each word linger before the next flip.
Customize
- Change the rotation axis from Y to X using
rotateX()for a top-to-bottom vertical page-turn effect instead of a horizontal spin. - Adjust the perspective value — lower values like
200pxcreate an extreme fisheye distortion, while1200pxproduces an almost-flat flip for subtle transitions. - Add a coloured edge illusion using
borderorbox-shadowon the container that stays visible during the rotation, simulating card thickness. - Stack multiple flip containers with staggered delays to cycle through a list of words in a slot-machine or rotating headline module.
- Replace text with icon SVGs or images on each face to create a flipping card reveal for portfolio thumbnails or feature highlights.
Watch out for
transform-style: preserve-3dmust be on the direct parent of the rotating element — it does not cascade down through extra wrapper divs without being re-declared.- Safari occasionally ignores
backface-visibility: hiddenon certain hardware; adding-webkit-backface-visibility: hiddenresolves the ghost-image issue in older Safari. - Mixing
overflow: hiddenorborder-radiuson apreserve-3dancestor collapses the 3D context in Chrome and Safari — use a wrapper outside the 3D layer for clipping.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 36+ | 9+ | 16+ | 36+ |
preserve-3d is well supported; always add -webkit-backface-visibility for Safari compatibility on the hidden faces.