20 CSS Cards16 / 20
3D Flip Business Card
Landscape business card that flips on hover AND focus-within (keyboard-accessible). Front shows avatar + name, back shows email/phone/site links. Reduced-motion disables the flip.
Published Updated
The code
<section class="card-16">
<div class="card-16__card" tabindex="0" aria-label="Business card for Alex Chen — flip to see contact details">
<div class="card-16__inner">
<div class="card-16__face card-16__front">
<div class="card-16__brand" aria-hidden="true">
<span class="card-16__mark"></span>
<span class="card-16__brandname">CHEN & CO</span>
</div>
<div class="card-16__id">
<h3 class="card-16__name">Alex Chen</h3>
<p class="card-16__role">Principal Designer</p>
</div>
<span class="card-16__hint">Hover to flip</span>
</div>
<div class="card-16__face card-16__back">
<span class="card-16__backbrand">CHEN & CO</span>
<address class="card-16__contact">
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
<a href="mailto:alex@chen.co">alex@chen.co</a>
</div>
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<a href="tel:+14155550142">+1 (415) 555-0142</a>
</div>
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
<a href="#site">alexchen.design</a>
</div>
</address>
</div>
</div>
</div>
</section><section class="card-16">
<div class="card-16__card" tabindex="0" aria-label="Business card for Alex Chen — flip to see contact details">
<div class="card-16__inner">
<div class="card-16__face card-16__front">
<div class="card-16__brand" aria-hidden="true">
<span class="card-16__mark"></span>
<span class="card-16__brandname">CHEN & CO</span>
</div>
<div class="card-16__id">
<h3 class="card-16__name">Alex Chen</h3>
<p class="card-16__role">Principal Designer</p>
</div>
<span class="card-16__hint">Hover to flip</span>
</div>
<div class="card-16__face card-16__back">
<span class="card-16__backbrand">CHEN & CO</span>
<address class="card-16__contact">
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
<a href="mailto:alex@chen.co">alex@chen.co</a>
</div>
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<a href="tel:+14155550142">+1 (415) 555-0142</a>
</div>
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
<a href="#site">alexchen.design</a>
</div>
</address>
</div>
</div>
</div>
</section>.card-16 {
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
box-sizing: border-box;
background: radial-gradient(ellipse at 30% 20%, #1e293b 0%, transparent 60%), radial-gradient(ellipse at 80% 80%, #0f172a 0%, transparent 60%), #050815;
font-family: 'Inter', system-ui, sans-serif;
--focus: #f5d97b;
--gold: #d4b063;
--gold-lite: #f5d97b;
}
.card-16 *,
.card-16 *::before,
.card-16 *::after {
box-sizing: border-box;
}
.card-16__card {
width: 360px;
height: 220px;
perspective: 1000px;
border-radius: 14px;
}
.card-16__card:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 6px;
border-radius: 14px;
}
.card-16__inner {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: transform 0.7s cubic-bezier(0.34, 1.2, 0.64, 1);
box-shadow: 0 30px 60px -12px rgba(0, 0, 0, 0.6), 0 18px 36px -18px rgba(212, 176, 99, 0.35);
}
.card-16__card:hover .card-16__inner,
.card-16__card:focus-within .card-16__inner {
transform: rotateY(180deg);
}
.card-16__face {
position: absolute;
inset: 0;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
border-radius: 14px;
padding: 26px 28px;
display: flex;
flex-direction: column;
overflow: hidden;
background: linear-gradient(135deg, rgba(212, 176, 99, 0.14) 0%, transparent 40%, transparent 60%, rgba(212, 176, 99, 0.06) 100%), linear-gradient(160deg, #16213e 0%, #0f172a 50%, #050815 100%);
border: 1px solid rgba(212, 176, 99, 0.28);
}
.card-16__face::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 60%;
height: 60%;
background: radial-gradient(circle at top right, rgba(245, 217, 123, 0.18), transparent 60%);
pointer-events: none;
}
.card-16__front {
justify-content: space-between;
}
.card-16__back {
transform: rotateY(180deg);
justify-content: space-between;
}
.card-16__brand {
display: flex;
align-items: center;
gap: 10px;
}
.card-16__mark {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, #f5d97b 0%, #d4b063 50%, #9a7a3d 100%);
box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.25), inset 0 2px 4px rgba(255, 255, 255, 0.3), 0 2px 6px rgba(212, 176, 99, 0.35);
position: relative;
}
.card-16__mark::before {
content: '';
position: absolute;
inset: 8px;
border-radius: 50%;
background: linear-gradient(135deg, #050815, #16213e);
}
.card-16__mark::after {
content: 'A';
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-family: Georgia, 'Times New Roman', serif;
font-size: 15px;
font-weight: 700;
color: #f5d97b;
text-shadow: 0 1px 2px rgba(0,0,0,0.6);
}
.card-16__brandname {
font-family: Georgia, 'Times New Roman', serif;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.24em;
color: var(--gold);
text-transform: uppercase;
}
.card-16__id {
margin-bottom: 12px;
}
.card-16__name {
font-family: Georgia, 'Times New Roman', serif;
font-size: 26px;
font-weight: 700;
margin: 0 0 4px;
color: #f8fafc;
letter-spacing: -0.005em;
line-height: 1.1;
}
.card-16__role {
font-size: 11px;
font-weight: 500;
color: rgba(245, 217, 123, 0.85);
margin: 0;
letter-spacing: 0.14em;
text-transform: uppercase;
}
.card-16__hint {
align-self: flex-end;
font-size: 9.5px;
color: rgba(148, 163, 184, 0.6);
letter-spacing: 0.14em;
text-transform: uppercase;
}
.card-16__backbrand {
font-family: Georgia, 'Times New Roman', serif;
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.28em;
color: rgba(212, 176, 99, 0.75);
text-transform: uppercase;
}
.card-16__contact {
font-style: normal;
display: flex;
flex-direction: column;
gap: 10px;
}
.card-16__row {
display: flex;
align-items: center;
gap: 12px;
min-height: 44px;
padding-top: 4px;
padding-bottom: 4px;
border-bottom: 1px solid rgba(212, 176, 99, 0.14);
}
.card-16__row:last-child {
border-bottom: 0;
}
.card-16__ico {
color: var(--gold);
flex-shrink: 0;
}
.card-16__row a {
color: #e2e8f0;
text-decoration: none;
font-size: 13px;
font-weight: 500;
letter-spacing: 0.01em;
transition: color 0.18s;
}
.card-16__row a:hover {
color: var(--gold-lite);
}
.card-16__row a:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 2px;
border-radius: 3px;
}
@media (prefers-reduced-motion: reduce) {
.card-16__inner {
transition: none;
}
.card-16__card:hover .card-16__inner,
.card-16__card:focus-within .card-16__inner {
transform: none;
}
}.card-16 {
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
box-sizing: border-box;
background: radial-gradient(ellipse at 30% 20%, #1e293b 0%, transparent 60%), radial-gradient(ellipse at 80% 80%, #0f172a 0%, transparent 60%), #050815;
font-family: 'Inter', system-ui, sans-serif;
--focus: #f5d97b;
--gold: #d4b063;
--gold-lite: #f5d97b;
}
.card-16 *,
.card-16 *::before,
.card-16 *::after {
box-sizing: border-box;
}
.card-16__card {
width: 360px;
height: 220px;
perspective: 1000px;
border-radius: 14px;
}
.card-16__card:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 6px;
border-radius: 14px;
}
.card-16__inner {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: transform 0.7s cubic-bezier(0.34, 1.2, 0.64, 1);
box-shadow: 0 30px 60px -12px rgba(0, 0, 0, 0.6), 0 18px 36px -18px rgba(212, 176, 99, 0.35);
}
.card-16__card:hover .card-16__inner,
.card-16__card:focus-within .card-16__inner {
transform: rotateY(180deg);
}
.card-16__face {
position: absolute;
inset: 0;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
border-radius: 14px;
padding: 26px 28px;
display: flex;
flex-direction: column;
overflow: hidden;
background: linear-gradient(135deg, rgba(212, 176, 99, 0.14) 0%, transparent 40%, transparent 60%, rgba(212, 176, 99, 0.06) 100%), linear-gradient(160deg, #16213e 0%, #0f172a 50%, #050815 100%);
border: 1px solid rgba(212, 176, 99, 0.28);
}
.card-16__face::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 60%;
height: 60%;
background: radial-gradient(circle at top right, rgba(245, 217, 123, 0.18), transparent 60%);
pointer-events: none;
}
.card-16__front {
justify-content: space-between;
}
.card-16__back {
transform: rotateY(180deg);
justify-content: space-between;
}
.card-16__brand {
display: flex;
align-items: center;
gap: 10px;
}
.card-16__mark {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, #f5d97b 0%, #d4b063 50%, #9a7a3d 100%);
box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.25), inset 0 2px 4px rgba(255, 255, 255, 0.3), 0 2px 6px rgba(212, 176, 99, 0.35);
position: relative;
}
.card-16__mark::before {
content: '';
position: absolute;
inset: 8px;
border-radius: 50%;
background: linear-gradient(135deg, #050815, #16213e);
}
.card-16__mark::after {
content: 'A';
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-family: Georgia, 'Times New Roman', serif;
font-size: 15px;
font-weight: 700;
color: #f5d97b;
text-shadow: 0 1px 2px rgba(0,0,0,0.6);
}
.card-16__brandname {
font-family: Georgia, 'Times New Roman', serif;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.24em;
color: var(--gold);
text-transform: uppercase;
}
.card-16__id {
margin-bottom: 12px;
}
.card-16__name {
font-family: Georgia, 'Times New Roman', serif;
font-size: 26px;
font-weight: 700;
margin: 0 0 4px;
color: #f8fafc;
letter-spacing: -0.005em;
line-height: 1.1;
}
.card-16__role {
font-size: 11px;
font-weight: 500;
color: rgba(245, 217, 123, 0.85);
margin: 0;
letter-spacing: 0.14em;
text-transform: uppercase;
}
.card-16__hint {
align-self: flex-end;
font-size: 9.5px;
color: rgba(148, 163, 184, 0.6);
letter-spacing: 0.14em;
text-transform: uppercase;
}
.card-16__backbrand {
font-family: Georgia, 'Times New Roman', serif;
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.28em;
color: rgba(212, 176, 99, 0.75);
text-transform: uppercase;
}
.card-16__contact {
font-style: normal;
display: flex;
flex-direction: column;
gap: 10px;
}
.card-16__row {
display: flex;
align-items: center;
gap: 12px;
min-height: 44px;
padding-top: 4px;
padding-bottom: 4px;
border-bottom: 1px solid rgba(212, 176, 99, 0.14);
}
.card-16__row:last-child {
border-bottom: 0;
}
.card-16__ico {
color: var(--gold);
flex-shrink: 0;
}
.card-16__row a {
color: #e2e8f0;
text-decoration: none;
font-size: 13px;
font-weight: 500;
letter-spacing: 0.01em;
transition: color 0.18s;
}
.card-16__row a:hover {
color: var(--gold-lite);
}
.card-16__row a:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 2px;
border-radius: 3px;
}
@media (prefers-reduced-motion: reduce) {
.card-16__inner {
transition: none;
}
.card-16__card:hover .card-16__inner,
.card-16__card:focus-within .card-16__inner {
transform: none;
}
}Here's a working CSS Card from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: 3D Flip Business Card
Source: https://codefronts.com/components/css-cards/3d-flip-business-card/
Landscape business card that flips on hover AND focus-within (keyboard-accessible). Front shows avatar + name, back shows email/phone/site links. Reduced-motion disables the flip.
## HTML
```html
<section class="card-16">
<div class="card-16__card" tabindex="0" aria-label="Business card for Alex Chen — flip to see contact details">
<div class="card-16__inner">
<div class="card-16__face card-16__front">
<div class="card-16__brand" aria-hidden="true">
<span class="card-16__mark"></span>
<span class="card-16__brandname">CHEN & CO</span>
</div>
<div class="card-16__id">
<h3 class="card-16__name">Alex Chen</h3>
<p class="card-16__role">Principal Designer</p>
</div>
<span class="card-16__hint">Hover to flip</span>
</div>
<div class="card-16__face card-16__back">
<span class="card-16__backbrand">CHEN & CO</span>
<address class="card-16__contact">
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
<a href="mailto:alex@chen.co">alex@chen.co</a>
</div>
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<a href="tel:+14155550142">+1 (415) 555-0142</a>
</div>
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
<a href="#site">alexchen.design</a>
</div>
</address>
</div>
</div>
</div>
</section>
```
## CSS
```css
.card-16 {
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
box-sizing: border-box;
background: radial-gradient(ellipse at 30% 20%, #1e293b 0%, transparent 60%), radial-gradient(ellipse at 80% 80%, #0f172a 0%, transparent 60%), #050815;
font-family: 'Inter', system-ui, sans-serif;
--focus: #f5d97b;
--gold: #d4b063;
--gold-lite: #f5d97b;
}
.card-16 *,
.card-16 *::before,
.card-16 *::after {
box-sizing: border-box;
}
.card-16__card {
width: 360px;
height: 220px;
perspective: 1000px;
border-radius: 14px;
}
.card-16__card:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 6px;
border-radius: 14px;
}
.card-16__inner {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: transform 0.7s cubic-bezier(0.34, 1.2, 0.64, 1);
box-shadow: 0 30px 60px -12px rgba(0, 0, 0, 0.6), 0 18px 36px -18px rgba(212, 176, 99, 0.35);
}
.card-16__card:hover .card-16__inner,
.card-16__card:focus-within .card-16__inner {
transform: rotateY(180deg);
}
.card-16__face {
position: absolute;
inset: 0;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
border-radius: 14px;
padding: 26px 28px;
display: flex;
flex-direction: column;
overflow: hidden;
background: linear-gradient(135deg, rgba(212, 176, 99, 0.14) 0%, transparent 40%, transparent 60%, rgba(212, 176, 99, 0.06) 100%), linear-gradient(160deg, #16213e 0%, #0f172a 50%, #050815 100%);
border: 1px solid rgba(212, 176, 99, 0.28);
}
.card-16__face::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 60%;
height: 60%;
background: radial-gradient(circle at top right, rgba(245, 217, 123, 0.18), transparent 60%);
pointer-events: none;
}
.card-16__front {
justify-content: space-between;
}
.card-16__back {
transform: rotateY(180deg);
justify-content: space-between;
}
.card-16__brand {
display: flex;
align-items: center;
gap: 10px;
}
.card-16__mark {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, #f5d97b 0%, #d4b063 50%, #9a7a3d 100%);
box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.25), inset 0 2px 4px rgba(255, 255, 255, 0.3), 0 2px 6px rgba(212, 176, 99, 0.35);
position: relative;
}
.card-16__mark::before {
content: '';
position: absolute;
inset: 8px;
border-radius: 50%;
background: linear-gradient(135deg, #050815, #16213e);
}
.card-16__mark::after {
content: 'A';
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-family: Georgia, 'Times New Roman', serif;
font-size: 15px;
font-weight: 700;
color: #f5d97b;
text-shadow: 0 1px 2px rgba(0,0,0,0.6);
}
.card-16__brandname {
font-family: Georgia, 'Times New Roman', serif;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.24em;
color: var(--gold);
text-transform: uppercase;
}
.card-16__id {
margin-bottom: 12px;
}
.card-16__name {
font-family: Georgia, 'Times New Roman', serif;
font-size: 26px;
font-weight: 700;
margin: 0 0 4px;
color: #f8fafc;
letter-spacing: -0.005em;
line-height: 1.1;
}
.card-16__role {
font-size: 11px;
font-weight: 500;
color: rgba(245, 217, 123, 0.85);
margin: 0;
letter-spacing: 0.14em;
text-transform: uppercase;
}
.card-16__hint {
align-self: flex-end;
font-size: 9.5px;
color: rgba(148, 163, 184, 0.6);
letter-spacing: 0.14em;
text-transform: uppercase;
}
.card-16__backbrand {
font-family: Georgia, 'Times New Roman', serif;
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.28em;
color: rgba(212, 176, 99, 0.75);
text-transform: uppercase;
}
.card-16__contact {
font-style: normal;
display: flex;
flex-direction: column;
gap: 10px;
}
.card-16__row {
display: flex;
align-items: center;
gap: 12px;
min-height: 44px;
padding-top: 4px;
padding-bottom: 4px;
border-bottom: 1px solid rgba(212, 176, 99, 0.14);
}
.card-16__row:last-child {
border-bottom: 0;
}
.card-16__ico {
color: var(--gold);
flex-shrink: 0;
}
.card-16__row a {
color: #e2e8f0;
text-decoration: none;
font-size: 13px;
font-weight: 500;
letter-spacing: 0.01em;
transition: color 0.18s;
}
.card-16__row a:hover {
color: var(--gold-lite);
}
.card-16__row a:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 2px;
border-radius: 3px;
}
@media (prefers-reduced-motion: reduce) {
.card-16__inner {
transition: none;
}
.card-16__card:hover .card-16__inner,
.card-16__card:focus-within .card-16__inner {
transform: none;
}
}
```Here's a working CSS Card from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: 3D Flip Business Card
Source: https://codefronts.com/components/css-cards/3d-flip-business-card/
Landscape business card that flips on hover AND focus-within (keyboard-accessible). Front shows avatar + name, back shows email/phone/site links. Reduced-motion disables the flip.
## HTML
```html
<section class="card-16">
<div class="card-16__card" tabindex="0" aria-label="Business card for Alex Chen — flip to see contact details">
<div class="card-16__inner">
<div class="card-16__face card-16__front">
<div class="card-16__brand" aria-hidden="true">
<span class="card-16__mark"></span>
<span class="card-16__brandname">CHEN & CO</span>
</div>
<div class="card-16__id">
<h3 class="card-16__name">Alex Chen</h3>
<p class="card-16__role">Principal Designer</p>
</div>
<span class="card-16__hint">Hover to flip</span>
</div>
<div class="card-16__face card-16__back">
<span class="card-16__backbrand">CHEN & CO</span>
<address class="card-16__contact">
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
<a href="mailto:alex@chen.co">alex@chen.co</a>
</div>
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<a href="tel:+14155550142">+1 (415) 555-0142</a>
</div>
<div class="card-16__row">
<svg class="card-16__ico" aria-hidden="true" focusable="false" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
<a href="#site">alexchen.design</a>
</div>
</address>
</div>
</div>
</div>
</section>
```
## CSS
```css
.card-16 {
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 40px);
box-sizing: border-box;
background: radial-gradient(ellipse at 30% 20%, #1e293b 0%, transparent 60%), radial-gradient(ellipse at 80% 80%, #0f172a 0%, transparent 60%), #050815;
font-family: 'Inter', system-ui, sans-serif;
--focus: #f5d97b;
--gold: #d4b063;
--gold-lite: #f5d97b;
}
.card-16 *,
.card-16 *::before,
.card-16 *::after {
box-sizing: border-box;
}
.card-16__card {
width: 360px;
height: 220px;
perspective: 1000px;
border-radius: 14px;
}
.card-16__card:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 6px;
border-radius: 14px;
}
.card-16__inner {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: transform 0.7s cubic-bezier(0.34, 1.2, 0.64, 1);
box-shadow: 0 30px 60px -12px rgba(0, 0, 0, 0.6), 0 18px 36px -18px rgba(212, 176, 99, 0.35);
}
.card-16__card:hover .card-16__inner,
.card-16__card:focus-within .card-16__inner {
transform: rotateY(180deg);
}
.card-16__face {
position: absolute;
inset: 0;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
border-radius: 14px;
padding: 26px 28px;
display: flex;
flex-direction: column;
overflow: hidden;
background: linear-gradient(135deg, rgba(212, 176, 99, 0.14) 0%, transparent 40%, transparent 60%, rgba(212, 176, 99, 0.06) 100%), linear-gradient(160deg, #16213e 0%, #0f172a 50%, #050815 100%);
border: 1px solid rgba(212, 176, 99, 0.28);
}
.card-16__face::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 60%;
height: 60%;
background: radial-gradient(circle at top right, rgba(245, 217, 123, 0.18), transparent 60%);
pointer-events: none;
}
.card-16__front {
justify-content: space-between;
}
.card-16__back {
transform: rotateY(180deg);
justify-content: space-between;
}
.card-16__brand {
display: flex;
align-items: center;
gap: 10px;
}
.card-16__mark {
width: 32px;
height: 32px;
border-radius: 50%;
background: linear-gradient(135deg, #f5d97b 0%, #d4b063 50%, #9a7a3d 100%);
box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.25), inset 0 2px 4px rgba(255, 255, 255, 0.3), 0 2px 6px rgba(212, 176, 99, 0.35);
position: relative;
}
.card-16__mark::before {
content: '';
position: absolute;
inset: 8px;
border-radius: 50%;
background: linear-gradient(135deg, #050815, #16213e);
}
.card-16__mark::after {
content: 'A';
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
font-family: Georgia, 'Times New Roman', serif;
font-size: 15px;
font-weight: 700;
color: #f5d97b;
text-shadow: 0 1px 2px rgba(0,0,0,0.6);
}
.card-16__brandname {
font-family: Georgia, 'Times New Roman', serif;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.24em;
color: var(--gold);
text-transform: uppercase;
}
.card-16__id {
margin-bottom: 12px;
}
.card-16__name {
font-family: Georgia, 'Times New Roman', serif;
font-size: 26px;
font-weight: 700;
margin: 0 0 4px;
color: #f8fafc;
letter-spacing: -0.005em;
line-height: 1.1;
}
.card-16__role {
font-size: 11px;
font-weight: 500;
color: rgba(245, 217, 123, 0.85);
margin: 0;
letter-spacing: 0.14em;
text-transform: uppercase;
}
.card-16__hint {
align-self: flex-end;
font-size: 9.5px;
color: rgba(148, 163, 184, 0.6);
letter-spacing: 0.14em;
text-transform: uppercase;
}
.card-16__backbrand {
font-family: Georgia, 'Times New Roman', serif;
font-size: 10.5px;
font-weight: 600;
letter-spacing: 0.28em;
color: rgba(212, 176, 99, 0.75);
text-transform: uppercase;
}
.card-16__contact {
font-style: normal;
display: flex;
flex-direction: column;
gap: 10px;
}
.card-16__row {
display: flex;
align-items: center;
gap: 12px;
min-height: 44px;
padding-top: 4px;
padding-bottom: 4px;
border-bottom: 1px solid rgba(212, 176, 99, 0.14);
}
.card-16__row:last-child {
border-bottom: 0;
}
.card-16__ico {
color: var(--gold);
flex-shrink: 0;
}
.card-16__row a {
color: #e2e8f0;
text-decoration: none;
font-size: 13px;
font-weight: 500;
letter-spacing: 0.01em;
transition: color 0.18s;
}
.card-16__row a:hover {
color: var(--gold-lite);
}
.card-16__row a:focus-visible {
outline: 2px solid var(--focus);
outline-offset: 2px;
border-radius: 3px;
}
@media (prefers-reduced-motion: reduce) {
.card-16__inner {
transition: none;
}
.card-16__card:hover .card-16__inner,
.card-16__card:focus-within .card-16__inner {
transform: none;
}
}
```How this works
The card is a landscape 360×220px panel wrapped in a container flipped via transform-style: preserve-3d and a rotateY(180deg) swap on :hover, :focus-within, and [data-flipped='true']. The face renders a hand-coded navy gradient (#0b1220 to #1a2544) topped with a gilt monogram medallion — a 44px circle filled with a radial #f4d47c-to-#8a6a2c gradient, embossed initials, and a 1px solid rgba(244,212,124,0.55) ring. The brand mark reads CHEN & CO in a letter-spacing: 0.24em gilt caps rule set at 10px.
The back face lives at transform: rotateY(180deg) with backface-visibility: hidden applied to both faces. Contact rows use a grid-template-columns: 14px 1fr layout so each icon glyph and its value line share a baseline. Gold hairline dividers between rows are border-block-end: 1px solid rgba(244,212,124,0.18) — thin enough to read as engraved rather than printed. All colour tokens (--card-navy, --card-gilt, --card-gilt-soft) are scoped under .xx-16 so nothing bleeds into a host design system.
Motion is GPU-accelerated by keeping the transform on the wrapper only and running it through transition: transform 720ms cubic-bezier(0.22, 1, 0.36, 1). A @media (prefers-reduced-motion: reduce) block drops the flip duration to 1ms and replaces the rotation with an opacity crossfade so vestibular-sensitive users still see the back face without spatial motion. The whole component is SSR-safe and React/Vue/Next-compatible because it ships zero JavaScript — the flip is :focus-within-driven, which means tabbing to any interactive element on either face triggers it without a state hook.
Make it yours
- Retint the navy face by editing
--card-navyand--card-navy-lift— try slate (#0f172ato#22304d) for a fintech register, or espresso (#1c1410to#33241a) for a hospitality feel. Contrast against gilt stays WCAG AA at every step. - Swap the monogram medallion for a mark by replacing the initials span with an inline SVG logo sized
28×28px. Keep thergba(244,212,124,0.55)ring — it reads as etched metal against dark faces and prevents the mark from looking pasted on. - Change orientation to portrait by flipping the wrapper to
220×360pxand shifting the back-face grid to a single column. The flip axis reads more like a passport than a card, which suits founder profiles and speaker-badge use cases. - Retune the flip feel via
transition-durationandcubic-bezier—520mswith(0.4, 0, 0.2, 1)reads snappier for dense dashboards, while900mswith(0.16, 1, 0.3, 1)reads more ceremonial for premium landing surfaces. - Add a hairline gilt border to the whole card with
box-shadow: 0 0 0 1px rgba(244,212,124,0.22) inset. Pair with afilter: drop-shadow(0 24px 32px rgba(8,12,24,0.45))on the wrapper for a floating-on-felt look on cream or ivory hero sections.
Gotchas — read before shipping
- Both faces need
backface-visibility: hiddenAND-webkit-backface-visibility: hidden— Safari on iOS 16 and older still needs the vendor prefix or the reversed face shows through as a mirrored ghost during the flip, which reads as a rendering bug on premium surfaces. - The
:focus-withinflip is the accessibility path — never gate the reveal behind hover only, or keyboard users tabbing to the contact links on the back face will be trapped facing a hidden panel. WCAG 2.1.1 and 2.4.7 both require the reversed side to be reachable without a pointer. - Contact links on the back face must clear the
44×44pxWCAG 2.5.5 target size. The gilt hairline rows tempt tight32pxrow heights — pad each anchor withpadding-block: 12pxso the tap surface exceeds spec even when the visible glyph is smaller. - The gilt gradient (
#f4d47con#0b1220) hits a10.8:1contrast ratio at10pxcaps, but tighteningletter-spacingbelow0.18emcollapses stroke gaps and drops legibility for low-vision users below WCAG 1.4.3 in practice — keep the tracking loose. - Serve
@media (prefers-reduced-motion: reduce)as a crossfade, not a hard cut — WCAG 2.3.3 asks for reduced motion, not zero feedback. A200msopacity swap between faces preserves the mental model of a two-sided card without triggering vestibular symptoms. - The flip transform promotes the wrapper to its own compositor layer, which is INP-safe on the interaction but expensive if you stack fifty of these on a directory page. Add
content-visibility: autoandcontain-intrinsic-size: 220px 360pxto off-screen cards or scroll jank spikes above the200msINP threshold.
Techniques used in this demo
3D transforms (perspective + preserve-3d):focus-withinMDN ↗tabindexMDN ↗radial-gradient()MDN ↗clamp()MDN ↗