Modern CSS Transform Effects
2D and 3D transforms - tilts, cubes, perspective and chained motion - driven only by hover and keyframes.
1Rotate 3D
A badge or tile that rocks around a diagonal axis with rotate3d() - eye-catching for feature icons. Class: fx-rotate-3d
<div class="flex flex-wrap items-center justify-center gap-4 p-4 h-full" style="min-height:200px">
<div class="fx-rotate-3d rounded-xl text-bg-primary grid text-4xl shadow-md" style="width:96px;height:96px;place-items:center">
<i class="bi bi-layers-fill" aria-hidden="true"></i>
</div>
<div class="fx-rotate-3d rounded-xl border grid text-4xl text-primary-ink" style="width:96px;height:96px;place-items:center;animation-delay:-2s">
<i class="bi bi-stars" aria-hidden="true"></i>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-rotate-3d { animation: fx-rotate-3d-rock 4s ease-in-out infinite; }
.fx-rotate-3d:hover { animation-play-state: paused; }
@keyframes fx-rotate-3d-rock {
0%, 100% { transform: perspective(600px) rotate3d(1, 1, 0, 0deg); }
50% { transform: perspective(600px) rotate3d(1, 1, 0, 32deg); }
}
@media (prefers-reduced-motion: reduce) {
.fx-rotate-3d, .fx-rotate-3d::before, .fx-rotate-3d::after, .fx-rotate-3d *, .fx-rotate-3d *::before, .fx-rotate-3d *::after { animation: none !important; transition: none !important; }
}2Scale & Rotate
A springy scale-and-twist on hover for icons, avatars, logos and small buttons. Class: fx-scale-rotate
<div class="flex flex-wrap items-center justify-center gap-4 p-4 h-full" style="min-height:200px">
<img src="../assets/img/avatar-4.svg" alt="Avatar" class="fx-scale-rotate rounded-full shadow-sm" style="width:72px;height:72px">
<button type="button" class="btn btn-primary btn-lg rounded-full fx-scale-rotate" aria-label="Favourite"><i class="bi bi-star-fill" aria-hidden="true"></i></button>
<img src="../assets/img/logo-3.svg" alt="Brand logo" class="fx-scale-rotate" style="width:110px">
</div>
/* CSS (already in assets/css/effects.css) */
.fx-scale-rotate { transition: transform .45s cubic-bezier(.34, 1.8, .64, 1); }
.fx-scale-rotate:hover, .fx-scale-rotate:focus-visible { transform: scale(1.15) rotate(-8deg); }
@media (prefers-reduced-motion: reduce) {
.fx-scale-rotate, .fx-scale-rotate::before, .fx-scale-rotate::after, .fx-scale-rotate *, .fx-scale-rotate *::before, .fx-scale-rotate *::after { animation: none !important; transition: none !important; }
}3Transform Chain
Chains translate, rotate and scale as separate properties with staggered timing for a lively hover. Class: fx-transform-chain
How to pitch a talk that gets accepted
$31.97
<div class="flex flex-wrap items-center justify-center gap-4 p-4 h-full" style="min-height:200px">
<div class="card border-0 shadow-sm fx-transform-chain" style="width:12rem">
<img src="https://images.unsplash.com/photo-1769798643655-e0f10f62c3fd?auto=format&fit=crop&w=1200&h=800&q=70" alt="Card cover" class="card-img-top object-cover" style="height:100px">
<div class="card-body py-2">
<h3 class="h6 mb-0">How to pitch a talk that gets accepted</h3>
<p class="small text-muted mb-0">$31.97</p>
</div>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-transform-chain { transition: translate .3s ease, rotate .5s cubic-bezier(.34, 1.56, .64, 1) .08s, scale .4s ease .16s; }
.fx-transform-chain:hover, .fx-transform-chain:focus-visible { translate: 0 -8px; rotate: -3deg; scale: 1.06; }
@supports not (translate: 0) {
.fx-transform-chain { transition: transform .4s cubic-bezier(.34, 1.56, .64, 1); }
.fx-transform-chain:hover, .fx-transform-chain:focus-visible { transform: translateY(-8px) rotate(-3deg) scale(1.06); }
}
@media (prefers-reduced-motion: reduce) {
.fx-transform-chain, .fx-transform-chain::before, .fx-transform-chain::after, .fx-transform-chain *, .fx-transform-chain *::before, .fx-transform-chain *::after { animation: none !important; transition: none !important; }
}