2D and 3D transforms - tilts, cubes, perspective and chained motion - driven only by hover and keyframes.
1Scale & Rotate
A springy scale-and-twist on hover for icons, avatars, logos and small buttons. Class: fx-scale-rotate
<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<img src="../assets/img/avatar-4.svg" alt="Avatar" class="fx-scale-rotate rounded-circle shadow-sm" style="width:72px;height:72px">
<button type="button" class="btn btn-primary btn-lg rounded-circle 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; }
}2Translate 3D
Stacked layers separate along the Z axis on hover, like an exploded view of your interface. Class: fx-translate-3d
Hover me
<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<div class="fx-translate-3d" style="width:150px;height:110px">
<div class="position-absolute top-0 start-0 w-100 h-100 rounded-3 border bg-body-tertiary">
</div>
<div class="position-absolute top-0 start-0 w-100 h-100 rounded-3" style="background:rgba(var(--wt-secondary-rgb), .45)">
</div>
<div class="position-absolute top-0 start-0 w-100 h-100 rounded-3" style="background:rgba(var(--wt-primary-rgb), .55)">
</div>
<div class="position-absolute top-0 start-0 w-100 h-100 rounded-3 d-grid text-white fw-semibold" style="place-items:center">
Hover me
</div>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-translate-3d { position: relative; transform-style: preserve-3d; transform: perspective(800px); transition: transform .6s cubic-bezier(.2, .8, .2, 1); }
.fx-translate-3d > * { transition: transform .6s cubic-bezier(.2, .8, .2, 1); }
.fx-translate-3d:hover { transform: perspective(800px) rotateX(48deg) rotateZ(-28deg); }
.fx-translate-3d:hover > :nth-child(1) { transform: translate3d(0, 0, 0); }
.fx-translate-3d:hover > :nth-child(2) { transform: translate3d(0, 0, 30px); }
.fx-translate-3d:hover > :nth-child(3) { transform: translate3d(0, 0, 60px); }
.fx-translate-3d:hover > :nth-child(4) { transform: translate3d(0, 0, 90px); }
@media (prefers-reduced-motion: reduce) {
.fx-translate-3d, .fx-translate-3d::before, .fx-translate-3d::after, .fx-translate-3d *, .fx-translate-3d *::before, .fx-translate-3d *::after { animation: none !important; transition: none !important; }
}