Cards & Layouts
Creative cards, Bento grids and morphing layouts.
Updated
How do you animate cards without hurting usability?
Card effects make grouped content such as products, articles or team members feel tangible. They combine CSS transforms for tilt and lift, backface-visibility for flip cards, backdrop-filter for glass surfaces, and CSS Grid with container queries for Bento layouts that adapt to their own width rather than the viewport.
How to choose, performance and accessibility
- Use a subtle Hover Lift or 3D Tilt Effect on clickable product cards, Flip Card when the back holds useful detail, and Stacked Cards or Card Morph for storytelling sections.
- Make the whole card one link or button, keep text readable during motion, and reduce the tilt for
prefers-reduced-motion. - 3D Tilt Effect, Glassmorphism, Basic Bento, Holo Tilt & Glare, Foil Shimmer and Page Curl Reveal are free with their code; the other cards come with Premium.
View source code
<div class="card-demo card-tilt" id="tiltCard">
<span class="tilt-content">3D Tilt</span>
</div>.card-demo {
width: 280px;
height: 180px;
background: var(--bg-card);
border-radius: var(--radius-xl);
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
position: relative;
cursor: pointer;
}
.card-tilt {
transform-style: preserve-3d;
transition: transform 0.1s;
}
.card-tilt:hover {
box-shadow: rgba(99, 102, 241, 0.3) 0px 25px 50px;
}
.card-tilt .tilt-content {
transform: translateZ(30px);
}
/* Variables du design system du site, dont ce code depend. Sans elles,
l'acheteur obtenait des coins carres et des couleurs par defaut (revue Owen).
Valeurs reprises de css/style.css — a adapter librement. */
.card-demo, .card-tilt {
--bg-card: #12121a;
--radius-xl: 1rem;
}
/* Le fond de carte est desormais sombre : sans couleur de texte declaree,
le libelle heritait du noir de la page hote et devenait illisible (revue Owen). */
.card-demo { color: #fff; }(function(){
// 3D Tilt Effect
const tiltCard = document.getElementById('tiltCard');
if (tiltCard) {
tiltCard.addEventListener('mousemove', (e) => {
const rect = tiltCard.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = (y - centerY) / 10;
const rotateY = (centerX - x) / 10;
tiltCard.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
tiltCard.addEventListener('mouseleave', () => {
tiltCard.style.transform = 'perspective(1000px) rotateX(0) rotateY(0)';
});
}
// Spotlight Effect
const spotlightCard = document.getElementById('spotlightCard');
if (spotlightCard) {
spotlightCard.addEventListener('mousemove', (e) => {
const rect = spotlightCard.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
spotlightCard.style.setProperty('--spotlight-x', x + 'px');
spotlightCard.style.setProperty('--spotlight-y', y + 'px');
});
}
// Card Morph Expand Effect
const morphExpandCard = document.getElementById('morphExpandCard');
if (morphExpandCard) {
morphExpandCard.addEventListener('click', () => {
morphExpandCard.classList.toggle('expanded');
});
// Close when clicking outside
document.addEventListener('click', (e) => {
if (!morphExpandCard.contains(e.target) && morphExpandCard.classList.contains('expanded')) {
morphExpandCard.classList.remove('expanded');
}
});
}
})();View source code
<div class="glass-bg" style="width:100%;min-height:300px;">
<div class="card-demo card-glass">
Glass
</div>
</div>.card-demo {
width: 280px;
height: 180px;
background: var(--bg-card);
border-radius: var(--radius-xl);
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
position: relative;
cursor: pointer;
}
.card-glass {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: rgba(0, 0, 0, 0.3) 0px 8px 32px;
}
.card-glass::before {
content: "";
position: absolute;
inset: 0px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, transparent 50%);
border-radius: inherit;
pointer-events: none;
}
.glass-bg {
background: linear-gradient(135deg, rgb(102, 126, 234) 0%, rgb(118, 75, 162) 50%, rgb(240, 147, 251) 100%);
}
/* Variables du design system du site, dont ce code depend. Sans elles,
l'acheteur obtenait des coins carres et des couleurs par defaut (revue Owen).
Valeurs reprises de css/style.css — a adapter librement. */
.glass-bg {
--bg-card: #12121a;
--radius-xl: 1rem;
}/* Pure CSS — no JavaScript required */Basic Bento
Simple bento grid with hover animations on each cell. Scale and glow effect.
Effect page →View source code
<div class="bento-container">
<div class="bento-grid bento-basic">
<div class="bento-cell cell-1">Featured</div>
<div class="bento-cell cell-2">A</div>
<div class="bento-cell cell-3">B</div>
<div class="bento-cell cell-4">Wide</div>
<div class="bento-cell cell-5">C</div>
<div class="bento-cell cell-6">D</div>
</div>
</div>.bento-container {
width: 100%;
max-width: 600px;
aspect-ratio: 4 / 3;
}
.bento-grid {
display: grid;
gap: 12px;
width: 100%;
height: 100%;
}
.bento-cell {
background: var(--bg-card);
border-radius: var(--radius-lg);
border: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 0.85rem;
color: var(--text-secondary);
position: relative;
overflow: hidden;
}
.bento-basic {
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr);
}
.bento-basic .cell-1 {
grid-area: span 2 / span 2;
}
.bento-basic .cell-2 {
grid-column: span 1;
}
.bento-basic .cell-3 {
grid-column: span 1;
}
.bento-basic .cell-4 {
grid-column: span 2;
}
.bento-basic .cell-5 {
grid-column: span 2;
}
.bento-basic .cell-6 {
grid-column: span 2;
}
.bento-basic .bento-cell {
transition: 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.bento-basic .bento-cell:hover {
transform: scale(1.05);
z-index: 10;
border-color: rgba(99, 102, 241, 0.5);
box-shadow: rgba(99, 102, 241, 0.3) 0px 20px 40px;
}
.bento-basic .bento-cell::before {
content: "";
position: absolute;
inset: 0px;
background: linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, transparent 50%);
opacity: 0;
transition: opacity 0.3s;
}
.bento-basic .bento-cell:hover::before {
opacity: 1;
}
.bento-images .cell-1 {
grid-area: span 2 / span 2;
}
.bento-images .cell-2 {
grid-column: span 2;
}
.bento-images .cell-3 {
grid-area: span 2 / span 1;
}
.bento-images .cell-4 {
grid-column: span 1;
}
.bento-images .cell-5 {
grid-column: span 2;
}
.bento-images .cell-6 {
grid-column: span 1;
}
.bento-images .bento-cell {
background-size: cover;
background-position: center center;
cursor: pointer;
}
.bento-images .cell-1 {
background: linear-gradient(135deg, rgb(102, 126, 234) 0%, rgb(118, 75, 162) 100%);
}
.bento-images .cell-2 {
background: linear-gradient(135deg, rgb(240, 147, 251) 0%, rgb(245, 87, 108) 100%);
}
.bento-images .cell-3 {
background: linear-gradient(135deg, rgb(79, 172, 254) 0%, rgb(0, 242, 254) 100%);
}
.bento-images .cell-4 {
background: linear-gradient(135deg, rgb(67, 233, 123) 0%, rgb(56, 249, 215) 100%);
}
.bento-images .cell-5 {
background: linear-gradient(135deg, rgb(250, 112, 154) 0%, rgb(254, 225, 64) 100%);
}
.bento-images .cell-6 {
background: linear-gradient(135deg, rgb(161, 140, 209) 0%, rgb(251, 194, 235) 100%);
}
.bento-images .bento-cell .overlay {
position: absolute;
inset: 0px;
background: rgba(0, 0, 0, 0.4);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: 0.4s;
}
.bento-images .bento-cell .overlay span {
color: white;
font-weight: 700;
font-size: 1rem;
transform: translateY(20px);
transition: transform 0.4s;
}
.bento-images .bento-cell:hover .overlay {
opacity: 1;
}
.bento-images .bento-cell:hover .overlay span {
transform: translateY(0px);
}
.bento-animated .cell-1 {
grid-area: span 1 / span 2;
}
.bento-animated .cell-2 {
grid-area: span 2 / span 1;
}
.bento-animated .cell-3 {
grid-area: span 2 / span 1;
}
.bento-animated .cell-4 {
grid-column: span 2;
}
.bento-animated .cell-5 {
grid-area: span 1 / span 2;
}
.bento-animated .cell-6 {
grid-area: span 1 / span 2;
}
.bento-animated .bento-cell {
opacity: 0;
transform: translateY(30px) scale(0.9);
animation: 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0s 1 normal forwards running bentoFadeIn;
}
.bento-animated .cell-1 {
animation-delay: 0.1s;
background: linear-gradient(135deg, rgb(99, 102, 241) 0%, rgb(139, 92, 246) 100%);
}
.bento-animated .cell-2 {
animation-delay: 0.2s;
background: linear-gradient(135deg, rgb(236, 72, 153) 0%, rgb(244, 63, 94) 100%);
}
.bento-animated .cell-3 {
animation-delay: 0.3s;
background: linear-gradient(135deg, rgb(6, 182, 212) 0%, rgb(59, 130, 246) 100%);
}
.bento-animated .cell-4 {
animation-delay: 0.4s;
background: linear-gradient(135deg, rgb(16, 185, 129) 0%, rgb(5, 150, 105) 100%);
}
.bento-animated .cell-5 {
animation-delay: 0.5s;
background: linear-gradient(135deg, rgb(245, 158, 11) 0%, rgb(239, 68, 68) 100%);
}
.bento-animated .cell-6 {
animation-delay: 0.6s;
background: linear-gradient(135deg, rgb(139, 92, 246) 0%, rgb(217, 70, 239) 100%);
}
.bento-animated .bento-cell span {
color: white;
font-weight: 700;
}
.bento-interactive .bento-cell {
cursor: pointer;
transition: 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
background: var(--bg-elevated);
}
.bento-interactive .bento-cell.expanded {
z-index: 100;
background: linear-gradient(135deg, rgb(99, 102, 241) 0%, rgb(139, 92, 246) 100%);
box-shadow: rgba(99, 102, 241, 0.4) 0px 25px 50px;
grid-area: span 2 / span 2 !important;
}
.bento-interactive .bento-cell .expand-icon {
width: 30px;
height: 30px;
border-radius: 50%;
background: rgba(99, 102, 241, 0.2);
display: flex;
align-items: center;
justify-content: center;
transition: 0.3s;
}
.bento-interactive .bento-cell:hover .expand-icon {
background: rgba(99, 102, 241, 0.4);
transform: scale(1.1);
}
.bento-interactive .bento-cell.expanded .expand-icon {
background: rgba(255, 255, 255, 0.2);
}
.bento-interactive .bento-cell.expanded .cell-content span {
color: white;
}
.bento-stats .cell-1 {
grid-area: span 2 / span 2;
}
.bento-stats .cell-2 {
grid-column: span 2;
}
.bento-stats .cell-3 {
grid-column: span 1;
}
.bento-stats .cell-4 {
grid-column: span 1;
}
.bento-stats .cell-5 {
grid-column: span 2;
}
.bento-stats .cell-6 {
grid-column: span 2;
}
.bento-stats .bento-cell {
flex-direction: column;
gap: 8px;
padding: 16px;
}
.bento-stats .cell-1 .stat-number {
font-size: 3rem;
}
.bento-stats .bento-cell:hover .stat-bar-fill {
width: var(--fill-width, 75%);
}
.bento-reveal .cell-1 {
grid-area: span 2 / span 2;
}
.bento-reveal .cell-2 {
grid-area: span 1 / span 2;
}
.bento-reveal .cell-3 {
grid-column: span 2;
}
.bento-reveal .cell-4 {
grid-area: span 1 / span 2;
}
.bento-reveal .cell-5 {
grid-column: span 2;
}
.bento-reveal .bento-cell {
cursor: pointer;
background: var(--bg-elevated);
}
.bento-reveal .bento-cell:hover .reveal-front {
opacity: 0;
transform: scale(1.2);
}
.bento-reveal .bento-cell:hover .reveal-back {
opacity: 1;
transform: scale(1);
}
.bento-reveal .bento-cell:hover {
border-color: rgba(99, 102, 241, 0.3);
box-shadow: rgba(99, 102, 241, 0.2) 0px 10px 30px;
}
.bento-cardstack .cell-1 {
grid-area: span 2 / span 2;
}
.bento-cardstack .cell-2 {
grid-area: span 2 / span 2;
}
.bento-cardstack .cell-3 {
grid-column: span 2;
}
.bento-cardstack .cell-4 {
grid-column: span 2;
}
.bento-cardstack .bento-cell {
padding: 16px;
background: var(--bg-elevated);
}
.bento-cardstack .bento-cell:hover .stacked-card:nth-child(1) {
transform: translate(-50%, -50%) translateX(-30%) rotate(-10deg);
}
.bento-cardstack .bento-cell:hover .stacked-card:nth-child(2) {
transform: translate(-50%, -50%) translateY(-5px);
}
.bento-cardstack .bento-cell:hover .stacked-card:nth-child(3) {
transform: translate(-50%, -50%) translateX(30%) rotate(10deg);
}
.bento-cardstack .bento-cell:hover .mini-card:nth-child(1) {
transform: translateY(-10px) rotate(-5deg);
}
.bento-cardstack .bento-cell:hover .mini-card:nth-child(2) {
transform: translateY(-15px);
}
.bento-cardstack .bento-cell:hover .mini-card:nth-child(3) {
transform: translateY(-10px) rotate(5deg);
}
.bento-responsive .bento-cell {
transition: 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.bento-responsive .bento-cell span {
color: white;
font-weight: 600;
font-size: 0.7rem;
}
.bento-responsive .bento-cell:hover {
transform: scale(1.05);
z-index: 10;
box-shadow: rgba(0, 0, 0, 0.3) 0px 15px 30px;
}
@keyframes bentoFadeIn {
100% {
opacity: 1;
transform: translateY(0px) scale(1);
}
}
/* Variables du design system du site, dont ce code depend. Sans elles,
l'acheteur obtenait des coins carres et des couleurs par defaut (revue Owen).
Valeurs reprises de css/style.css — a adapter librement. */
.bento-container {
--bg-card: #12121a;
--bg-elevated: #1a1a24;
--border: rgba(255, 255, 255, 0.08);
--radius-lg: 0.75rem;
--text-secondary: #a1a1aa;
}/* Pure CSS — no JavaScript required */Responsive Bento
Grid that elegantly reorganizes. Resize the container to see the effect.
Effect page →Grid to List Toggle
Items morphing between grid and list layout with smooth CSS grid transitions.
Effect page →Card Expand to Full
Card that expands from its position to full screen with position/size transition.
Effect page →Masonry to Grid
Items that animate from an organic masonry layout to a strict grid and back.
Effect page →Sidebar to Overlay
Sidebar that transforms into a full-screen overlay with smooth content reflow.
Effect page →Split Screen Morph
Two-panel layout morphing between 50/50, 70/30, and single panel with CSS flex transitions.
Effect page →Stacked to Spread
Stacked cards that spread into a grid with elastic cubic-bezier animation.
Effect page →Gallery to Slideshow
Image gallery morphing into full-screen slideshow with position animation and navigation.
Effect page →Holographic Card 3D
Iridescent holographic card on hover, premium trading-card style. conic-gradient + blend modes + 3D transform. Zero JavaScript.
Effect page →Shape-Aware Shadows
Shadows, borders and outlines that hug non-rectangular shapes with border-shape: pointed tag, notched ticket, chat bubble. Automatic drop-shadow fallback on every browser.
💡 Perfect for: promo badges, event tickets, chat bubbles, pointed tooltips, pricing cards.
Effect page →Holo Tilt & Glare
Pointer-driven holographic card: 3D tilt (rAF + lerp), iridescent glare tracking the cursor and a foil layer in inverse parallax — the depth of a real holo card. Elastic return on leave, reduced-motion fallback.
💡 Ideal for: premium loyalty cards, player badges, invitations, collectibles.
Effect page →View source code
<div class="htg-wrap" tabindex="0" aria-label="Holographic card that follows the pointer">
<div class="htg-card">
<span class="htg-glare" aria-hidden="true">
</span>
<span class="htg-foil" aria-hidden="true">
</span>
<span class="htg-content">
<span class="htg-badge">GOLD MEMBER</span>
<strong class="htg-name">A. Dubois</strong>
<span class="htg-num">MBR‑2026‑0042</span>
</span>
</div>
</div>.htg-wrap {
perspective: 900px;
display: inline-block;
border-radius: 16px;
}
.htg-wrap:focus-visible {
outline: rgb(168, 85, 247) solid 2px;
outline-offset: 6px;
}
.htg-card {
position: relative;
width: 250px;
height: 156px;
border-radius: 14px;
overflow: hidden;
background: radial-gradient(120% 160% at var(--htg-mx, 70%) var(--htg-my, 20%), rgba(255,255,255,.16), transparent 55%),
conic-gradient(from 230deg at 40% 30%, #1c1440, #232e63, #14324d, #3a1c55, #1c1440);
transform: rotateX(var(--htg-ry, 0deg)) rotateY(var(--htg-rx, 0deg));
box-shadow: rgba(0, 0, 0, 0.5) 0px 18px 40px;
transform-style: preserve-3d;
will-change: transform;
}
.htg-glare {
position: absolute;
inset: 0px;
pointer-events: none;
background: conic-gradient(from 0deg at var(--htg-mx, 70%) var(--htg-my, 25%),
rgba(98,230,255,.5), rgba(255,138,225,.45), rgba(255,233,92,.4), rgba(177,140,255,.45), rgba(125,255,196,.4), rgba(98,230,255,.5));
mix-blend-mode: screen;
opacity: 0.62;
filter: blur(6px);
}
.htg-foil {
position: absolute;
inset: -30%;
pointer-events: none;
background: repeating-linear-gradient(104deg, rgba(255, 255, 255, 0.09) 0px, rgba(255, 255, 255, 0.09) 1px, transparent 1px, transparent 3px, rgba(255, 255, 255, 0.043) 3px, rgba(255, 255, 255, 0.043) 4px, transparent 4px, transparent 7px);
mix-blend-mode: color-dodge;
transform: translate(var(--htg-fx, 0px), var(--htg-fy, 0px));
}
.htg-content {
position: absolute;
inset: 0px;
padding: 16px 18px;
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: 3px;
transform: translateZ(24px);
text-shadow: rgba(0, 0, 0, 0.65) 0px 1px 3px;
}
.htg-badge {
align-self: flex-start;
font-size: 0.58rem;
font-weight: 800;
letter-spacing: 0.16em;
color: rgb(125, 255, 196);
border: 1px solid rgba(125, 255, 196, 0.45);
border-radius: 20px;
padding: 3px 9px;
margin-bottom: auto;
}
.htg-name {
font-size: 1.05rem;
color: rgb(255, 255, 255);
}
.htg-num {
font-size: 0.7rem;
letter-spacing: 0.18em;
color: rgba(255, 255, 255, 0.75);
}(function() {
/* fx-0821 — Holo Tilt & Glare : tilt + glare + foil pilotés au pointeur (rAF + lerp) */
function initHtg() {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
document.querySelectorAll('.htg-wrap').forEach(function(wrap) {
var card = wrap.querySelector('.htg-card');
if (!card) return;
var tx = 0, ty = 0, tmx = 70, tmy = 25, x = 0, y = 0, mx = 70, my = 25, raf = null;
function loop() {
x += (tx - x) * 0.12; y += (ty - y) * 0.12; mx += (tmx - mx) * 0.12; my += (tmy - my) * 0.12;
card.style.setProperty('--htg-rx', x.toFixed(2) + 'deg');
card.style.setProperty('--htg-ry', y.toFixed(2) + 'deg');
card.style.setProperty('--htg-mx', mx.toFixed(1) + '%');
card.style.setProperty('--htg-my', my.toFixed(1) + '%');
card.style.setProperty('--htg-fx', (-(mx - 50) * 0.5).toFixed(1) + 'px');
card.style.setProperty('--htg-fy', (-(my - 50) * 0.4).toFixed(1) + 'px');
if (Math.abs(tx - x) > 0.05 || Math.abs(ty - y) > 0.05 || Math.abs(tmx - mx) > 0.2) raf = requestAnimationFrame(loop);
else raf = null;
}
function kick() { if (!raf) raf = requestAnimationFrame(loop); }
wrap.addEventListener('pointermove', function(e) {
var r = card.getBoundingClientRect();
var px = (e.clientX - r.left) / r.width, py = (e.clientY - r.top) / r.height;
tx = (px - 0.5) * 22; ty = -(py - 0.5) * 18; tmx = px * 100; tmy = py * 100; kick();
});
wrap.addEventListener('pointerleave', function() { tx = 0; ty = 0; tmx = 70; tmy = 25; kick(); });
});
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initHtg);
else initHtg();
})();Foil Shimmer
Stamped holographic foil in pure CSS: three text-clipped layers — animated iridescent gradient, metal grain, specular sweep. Foil-border pill variant included. Hover speeds up the shimmer.
💡 Ideal for: premium badges, pricing card headlines, limited-edition labels.
Effect page →View source code
<div class="fsh-demo">
<span class="fsh-foil">
<span class="fsh-text fsh-big">FOIL</span>
</span>
<span class="fsh-pill">
<span class="fsh-inner">
<span class="fsh-foil">
<span class="fsh-text">✦ PRO</span>
</span>
</span>
</span>
</div>.fsh-demo {
display: flex;
flex-direction: column;
align-items: center;
gap: 18px;
}
.fsh-foil {
display: inline-block;
}
.fsh-text {
background-image: linear-gradient(108deg, transparent 30%, rgba(255, 255, 255, 0.5) 47%, rgba(255, 255, 255, 0.95) 50%, rgba(255, 255, 255, 0.5) 53%, transparent 70%), repeating-linear-gradient(104deg, rgba(255, 255, 255, 0.07) 0px, rgba(255, 255, 255, 0.07) 1px, transparent 1px, transparent 3px, rgba(200, 175, 90, 0.04) 3px, rgba(200, 175, 90, 0.04) 4px, transparent 4px, transparent 6px), linear-gradient(135deg, rgb(255, 215, 0) 0%, rgb(255, 192, 203) 18%, rgb(232, 234, 240) 36%, rgb(0, 229, 255) 54%, rgb(199, 125, 255) 72%, rgb(232, 234, 240) 84%, rgb(255, 215, 0) 100%);
background-size: 350% 100%, auto, 300% 100%;
background-position: -120% 0px, 0px 0px, 0% 50%;
background-blend-mode: screen, overlay, normal;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
display: inline-block;
font-weight: 900;
animation: fsh-pan var(--fsh-speed, 3.2s) linear infinite;
}
.fsh-big {
font-size: 3.2rem;
letter-spacing: 0.04em;
}
.fsh-foil:hover .fsh-text {
--fsh-speed: .7s;
}
.fsh-pill {
display: inline-block;
padding: 2px;
border-radius: 20px;
background: linear-gradient(135deg, rgb(255, 215, 0), rgb(255, 192, 203) 25%, rgb(0, 229, 255) 55%, rgb(199, 125, 255) 80%, rgb(255, 215, 0)) 0% 0% / 300% 100%;
animation: 3.2s linear 0s infinite normal none running fsh-pan-border;
}
@keyframes fsh-pan {
0% {
background-position: -120% 0px, 0px 0px, 0% 50%;
}
40% {
background-position: -120% 0px, 0px 0px, 120% 50%;
}
65% {
background-position: 270% 0px, 0px 0px, 195% 50%;
}
100% {
background-position: 270% 0px, 0px 0px, 300% 50%;
}
}
@keyframes fsh-pan-border {
100% {
background-position: 300% 50%;
}
}
.fsh-inner {
display: inline-block;
background: rgb(16, 16, 24);
border-radius: 18px;
padding: 6px 14px;
}
.fsh-pill .fsh-text {
font-size: 0.85rem;
letter-spacing: 0.1em;
}/* Pure CSS — no JavaScript required */Holographic Sticker Peel
Die-cut holographic sticker that peels off: hover lifts the corner, click peels it three-quarters away. The back exposes grey glue and inverted iridescence — two interpolated clip-paths, growing shadow, glue-stretch.
💡 Ideal for: e-commerce promo stickers, “new” badges, event tags.
Effect page →Prismatic Refraction Card
Chromatic-dispersion glass: the edges split light into red/cyan fringes while a rainbow band sweeps the surface following the cursor. rAF + lerp 3D tilt, saturated backdrop-filter, scrim-guaranteed readability.
💡 Ideal for: premium pricing cards, landing heroes, featured-capability widgets.
Effect page →Holo Pack Opening
TCG-Pocket-style booster opening: a spark cuts the top of the wrapper along a glowing line, the strip tears away and flutters off, and the cards slide out through the opening in cascade. Then inspection — auto zoom, click to flip (3D flip with a real back), ‹ › and keyboard navigation. 1 to N cards, replayable (fresh pack), zero dependencies.
💡 Ideal for: reward reveals, gift cards, loot boxes, gamified onboarding.
Effect page →Page Curl Reveal
Hover: the corner curls like a real page. Click: it peels away entirely to reveal the hidden content, click again to lay it back. Animated gradient fold, shadow and clip-path, accessible toggle.
💡 Perfect for: revealing a promo code, a surprise, a card back, a content teaser.
Effect page →View source code
<button class="pcr-card" type="button" aria-label="Hover or activate to curl the page and reveal the promo code">
<div class="pcr-under"><div><strong>WELCOME20</strong><span>-20% on everything</span></div></div>
<div class="pcr-page">Hover the corner ↗</div>
<span class="pcr-curl" aria-hidden="true"></span>
</button>.pcr-card {
position: relative;
width: 250px;
height: 160px;
border-radius: 12px;
overflow: hidden;
background: #101018;
border: 1px solid rgba(255,255,255,.08);
}
.pcr-under {
position: absolute;
inset: 0;
display: grid;
place-items: center;
text-align: center;
background: radial-gradient(circle at 70% 20%, rgba(34,255,170,.18), transparent 55%), #0d1512;
}
.pcr-under strong {
font-size: 1.25rem; color: #22ffaa; letter-spacing: .06em
}
.pcr-under span {
display: block; font-size: .68rem; color: #7fbfa8; margin-top: 4px; letter-spacing: .12em; text-transform: uppercase
}
.pcr-page {
position: absolute;
inset: 0;
display: grid;
place-items: center;
background: linear-gradient(135deg, #262640, #16162a);
color: #cfcfe8;
font-size: .8rem;
letter-spacing: .04em;
clip-path: polygon(0 0, calc(100% - var(--pcr-c)) 0, 100% var(--pcr-c), 100% 100%, 0 100%);
transition: clip-path .55s cubic-bezier(.25,.8,.3,1);
--pcr-c: 34px;
}
.pcr-curl {
position: absolute;
top: 0; right: 0;
width: var(--pcr-c);
height: var(--pcr-c);
--pcr-c: 34px;
background: linear-gradient(225deg, transparent 48%, #3d3d66 50%, #52528a 70%, #2c2c4d 100%);
border-bottom-left-radius: 55%;
box-shadow: -5px 5px 12px rgba(0,0,0,.45);
transition: width .55s cubic-bezier(.25,.8,.3,1), height .55s cubic-bezier(.25,.8,.3,1);
pointer-events: none;
}
.pcr-card:hover .pcr-page, .pcr-card:focus-visible .pcr-page {
--pcr-c: 150px
}
.pcr-card:hover .pcr-curl, .pcr-card:focus-visible .pcr-curl {
width: 150px; height: 150px
}
.pcr-card:focus-visible {
outline: 2px solid #a78bfa; outline-offset: 3px
}
.pcr-card[aria-pressed="true"] .pcr-page {
--pcr-c: 380px
}
.pcr-card[aria-pressed="true"] .pcr-curl {
width: 380px; height: 380px; opacity: 0; transition: width .6s cubic-bezier(.25,.8,.3,1), height .6s cubic-bezier(.25,.8,.3,1), opacity .35s ease .3s
}
.pcr-card[aria-pressed="true"]:hover .pcr-page {
--pcr-c: 380px
}
@media (prefers-reduced-motion: reduce) {
.pcr-page, .pcr-curl {
transition: none
}
}(function() {
/* fx-0775 — Page Curl Reveal : clic = révélation complète (toggle), survol = pli */
document.querySelectorAll('.pcr-card').forEach(function(card) {
card.setAttribute('aria-pressed', 'false');
card.addEventListener('click', function() {
card.setAttribute('aria-pressed', card.getAttribute('aria-pressed') !== 'true');
});
});
})();Interactive Ghost Card
A true-3D neon collectible card: a ghost skull floats behind the glass and shifts perspective as the card turns. Drag it, hover it, or let it sway on its own.
💡 Perfect for: game cards, premium membership cards, drop launch pages.
Poster Pop-Out 3D
The poster tilts and its character steps out of the frame at the top, in relief, with a shadow and a colour glow. Hover, keyboard focus or tap; swap in your own posters.
💡 Perfect for: film or series posters, game covers, book covers.
Advent Calendar
Interactive advent calendar: 24 doors that open on a 3D hinge and reveal a bouncing surprise behind them, with the current day's door highlighted. Surprises and number of doors are customisable.
💡 Perfect for: December campaigns, gamification, loyalty programs, daily contests, progressive reveals, festive e-commerce.
Ribbon Bow Wrap
Wraps a card in an animated golden ribbon with a knotting bow on hover. Click to lock the wrapping. Ribbon colour and card content are fully customisable — works on any card or offer.
💡 Perfect for: gift cards, Christmas offers, greeting messages, product highlights, digital packaging.