26 CSS Dividers16 / 26
Wedding Heart Icon Divider CSS
An invitation-grade divider: two hairlines fading toward a centred heart, with the heart drawn by clip-path rather than an emoji — so it inherits your palette, scales cleanly, and never renders as someone else's cartoon glyph. A slow, tiny beat animation adds life without turning a wedding page into a toy, and the whole thing is one flex row.
Published Updated
The code
<section class="div-16" aria-label="Wedding heart icon divider demo">
<div class="div-16__stage">
<div class="div-16__frame">
<p class="div-16__eyebrow">TOGETHER WITH THEIR FAMILIES</p>
<h2 class="div-16__names">Amara <span class="div-16__amp">&</span> Elias</h2>
<div class="div-16__rule" role="separator" aria-label="Divider">
<span class="div-16__heart" aria-hidden="true"></span>
</div>
<p class="div-16__date">SATURDAY, THE TWELFTH OF SEPTEMBER<br>TWO THOUSAND TWENTY-SEVEN</p>
<div class="div-16__rule div-16__rule--short" role="separator" aria-label="Divider">
<span class="div-16__dot" aria-hidden="true"></span>
</div>
<p class="div-16__place">The Old Orangery · Bath, England</p>
</div>
<p class="div-16__chip">clip-path:path() heart · inward-fading rules · 4% beat</p>
</div>
</section><section class="div-16" aria-label="Wedding heart icon divider demo">
<div class="div-16__stage">
<div class="div-16__frame">
<p class="div-16__eyebrow">TOGETHER WITH THEIR FAMILIES</p>
<h2 class="div-16__names">Amara <span class="div-16__amp">&</span> Elias</h2>
<div class="div-16__rule" role="separator" aria-label="Divider">
<span class="div-16__heart" aria-hidden="true"></span>
</div>
<p class="div-16__date">SATURDAY, THE TWELFTH OF SEPTEMBER<br>TWO THOUSAND TWENTY-SEVEN</p>
<div class="div-16__rule div-16__rule--short" role="separator" aria-label="Divider">
<span class="div-16__dot" aria-hidden="true"></span>
</div>
<p class="div-16__place">The Old Orangery · Bath, England</p>
</div>
<p class="div-16__chip">clip-path:path() heart · inward-fading rules · 4% beat</p>
</div>
</section>.div-16 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--div-16-bg);
--div-16-bg: oklch(0.975 0.012 30);
--div-16-card: oklch(1 0.004 30);
--div-16-ink: oklch(0.32 0.03 25);
--div-16-mut: oklch(0.56 0.03 25);
--div-16-line: oklch(0.32 0.03 25/.24);
--div-16-acc: oklch(0.68 0.11 18);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
color: var(--div-16-ink);
}
.div-16 *,
.div-16 *::before,
.div-16 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.div-16__stage {
min-height: 100svh;
display: grid;
place-content: center;
justify-items: center;
gap: 20px;
padding: clamp(24px,5vw,60px) clamp(20px,5vw,56px);
background: radial-gradient(100% 70% at 50% 0%,oklch(0.99 0.014 28),transparent);
}
.div-16__frame {
width: min(92vw,520px);
background: var(--div-16-card);
border: 1px solid var(--div-16-line);
border-radius: 4px;
padding: clamp(34px,6vw,62px) clamp(24px,5vw,52px);
text-align: center;
display: grid;
justify-items: center;
gap: clamp(16px,3vw,26px);
box-shadow: 0 20px 50px oklch(0.32 0.03 25/.09);
position: relative;
}
.div-16__frame::before {
content: '';
position: absolute;
inset: 9px;
border: 1px solid oklch(0.68 0.11 18/.3);
border-radius: 2px;
pointer-events: none;
}
.div-16__eyebrow {
font-size: 10.5px;
letter-spacing: .3em;
color: var(--div-16-mut);
}
.div-16__names {
font-family: Georgia,'Iowan Old Style',serif;
font-size: clamp(32px,7vw,62px);
line-height: 1.08;
font-weight: 400;
letter-spacing: .01em;
font-style: italic;
}
.div-16__amp {
color: var(--div-16-acc);
font-size: .72em;
padding: 0 .06em;
}
.div-16__rule {
width: 100%;
max-width: 320px;
display: flex;
align-items: center;
gap: 14px;
}
.div-16__rule::before,
.div-16__rule::after {
content: '';
flex: 1 1 0;
height: 1px;
}
.div-16__rule::before {
background: linear-gradient(90deg,transparent,var(--div-16-line) 88%);
}
.div-16__rule::after {
background: linear-gradient(90deg,var(--div-16-line) 12%,transparent);
}
.div-16__rule--short {
max-width: 180px;
}
.div-16__heart {
width: 17px;
height: 17px;
flex: none;
background: var(--div-16-acc);
clip-path: path('M8.5 15.6 1.9 9.1a4.1 4.1 0 1 1 6.6-4.7 4.1 4.1 0 1 1 6.6 4.7Z');
animation: div-16-beat 2.4s ease-in-out infinite;
}
@keyframes div-16-beat {
0%,
72%,
100% {
scale: 1;
}
80% {
scale: 1.04;
}
88% {
scale: 1;
}
}
.div-16__dot {
width: 5px;
height: 5px;
flex: none;
border-radius: 99px;
background: var(--div-16-acc);
opacity: .8;
}
.div-16__date {
font-size: 11.5px;
letter-spacing: .22em;
line-height: 2.2;
color: var(--div-16-mut);
}
.div-16__place {
font-family: Georgia,serif;
font-style: italic;
font-size: clamp(14px,1.9vw,17px);
color: var(--div-16-ink);
}
.div-16__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11px;
color: var(--div-16-mut);
padding: 8px 14px;
border: 1px solid var(--div-16-line);
border-radius: 99px;
}
@media (prefers-reduced-motion: reduce) {
.div-16__heart {
animation: none;
}
}.div-16 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--div-16-bg);
--div-16-bg: oklch(0.975 0.012 30);
--div-16-card: oklch(1 0.004 30);
--div-16-ink: oklch(0.32 0.03 25);
--div-16-mut: oklch(0.56 0.03 25);
--div-16-line: oklch(0.32 0.03 25/.24);
--div-16-acc: oklch(0.68 0.11 18);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
color: var(--div-16-ink);
}
.div-16 *,
.div-16 *::before,
.div-16 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.div-16__stage {
min-height: 100svh;
display: grid;
place-content: center;
justify-items: center;
gap: 20px;
padding: clamp(24px,5vw,60px) clamp(20px,5vw,56px);
background: radial-gradient(100% 70% at 50% 0%,oklch(0.99 0.014 28),transparent);
}
.div-16__frame {
width: min(92vw,520px);
background: var(--div-16-card);
border: 1px solid var(--div-16-line);
border-radius: 4px;
padding: clamp(34px,6vw,62px) clamp(24px,5vw,52px);
text-align: center;
display: grid;
justify-items: center;
gap: clamp(16px,3vw,26px);
box-shadow: 0 20px 50px oklch(0.32 0.03 25/.09);
position: relative;
}
.div-16__frame::before {
content: '';
position: absolute;
inset: 9px;
border: 1px solid oklch(0.68 0.11 18/.3);
border-radius: 2px;
pointer-events: none;
}
.div-16__eyebrow {
font-size: 10.5px;
letter-spacing: .3em;
color: var(--div-16-mut);
}
.div-16__names {
font-family: Georgia,'Iowan Old Style',serif;
font-size: clamp(32px,7vw,62px);
line-height: 1.08;
font-weight: 400;
letter-spacing: .01em;
font-style: italic;
}
.div-16__amp {
color: var(--div-16-acc);
font-size: .72em;
padding: 0 .06em;
}
.div-16__rule {
width: 100%;
max-width: 320px;
display: flex;
align-items: center;
gap: 14px;
}
.div-16__rule::before,
.div-16__rule::after {
content: '';
flex: 1 1 0;
height: 1px;
}
.div-16__rule::before {
background: linear-gradient(90deg,transparent,var(--div-16-line) 88%);
}
.div-16__rule::after {
background: linear-gradient(90deg,var(--div-16-line) 12%,transparent);
}
.div-16__rule--short {
max-width: 180px;
}
.div-16__heart {
width: 17px;
height: 17px;
flex: none;
background: var(--div-16-acc);
clip-path: path('M8.5 15.6 1.9 9.1a4.1 4.1 0 1 1 6.6-4.7 4.1 4.1 0 1 1 6.6 4.7Z');
animation: div-16-beat 2.4s ease-in-out infinite;
}
@keyframes div-16-beat {
0%,
72%,
100% {
scale: 1;
}
80% {
scale: 1.04;
}
88% {
scale: 1;
}
}
.div-16__dot {
width: 5px;
height: 5px;
flex: none;
border-radius: 99px;
background: var(--div-16-acc);
opacity: .8;
}
.div-16__date {
font-size: 11.5px;
letter-spacing: .22em;
line-height: 2.2;
color: var(--div-16-mut);
}
.div-16__place {
font-family: Georgia,serif;
font-style: italic;
font-size: clamp(14px,1.9vw,17px);
color: var(--div-16-ink);
}
.div-16__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11px;
color: var(--div-16-mut);
padding: 8px 14px;
border: 1px solid var(--div-16-line);
border-radius: 99px;
}
@media (prefers-reduced-motion: reduce) {
.div-16__heart {
animation: none;
}
}Here's a working CSS Divider 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: Wedding Heart Icon Divider CSS
Source: https://codefronts.com/snippets/css-dividers/romantic-dividers/
An invitation-grade divider: two hairlines fading toward a centred heart, with the heart drawn by clip-path rather than an emoji — so it inherits your palette, scales cleanly, and never renders as someone else's cartoon glyph. A slow, tiny beat animation adds life without turning a wedding page into a toy, and the whole thing is one flex row.
## HTML
```html
<section class="div-16" aria-label="Wedding heart icon divider demo">
<div class="div-16__stage">
<div class="div-16__frame">
<p class="div-16__eyebrow">TOGETHER WITH THEIR FAMILIES</p>
<h2 class="div-16__names">Amara <span class="div-16__amp">&</span> Elias</h2>
<div class="div-16__rule" role="separator" aria-label="Divider">
<span class="div-16__heart" aria-hidden="true"></span>
</div>
<p class="div-16__date">SATURDAY, THE TWELFTH OF SEPTEMBER<br>TWO THOUSAND TWENTY-SEVEN</p>
<div class="div-16__rule div-16__rule--short" role="separator" aria-label="Divider">
<span class="div-16__dot" aria-hidden="true"></span>
</div>
<p class="div-16__place">The Old Orangery · Bath, England</p>
</div>
<p class="div-16__chip">clip-path:path() heart · inward-fading rules · 4% beat</p>
</div>
</section>
```
## CSS
```css
.div-16 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--div-16-bg);
--div-16-bg: oklch(0.975 0.012 30);
--div-16-card: oklch(1 0.004 30);
--div-16-ink: oklch(0.32 0.03 25);
--div-16-mut: oklch(0.56 0.03 25);
--div-16-line: oklch(0.32 0.03 25/.24);
--div-16-acc: oklch(0.68 0.11 18);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
color: var(--div-16-ink);
}
.div-16 *,
.div-16 *::before,
.div-16 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.div-16__stage {
min-height: 100svh;
display: grid;
place-content: center;
justify-items: center;
gap: 20px;
padding: clamp(24px,5vw,60px) clamp(20px,5vw,56px);
background: radial-gradient(100% 70% at 50% 0%,oklch(0.99 0.014 28),transparent);
}
.div-16__frame {
width: min(92vw,520px);
background: var(--div-16-card);
border: 1px solid var(--div-16-line);
border-radius: 4px;
padding: clamp(34px,6vw,62px) clamp(24px,5vw,52px);
text-align: center;
display: grid;
justify-items: center;
gap: clamp(16px,3vw,26px);
box-shadow: 0 20px 50px oklch(0.32 0.03 25/.09);
position: relative;
}
.div-16__frame::before {
content: '';
position: absolute;
inset: 9px;
border: 1px solid oklch(0.68 0.11 18/.3);
border-radius: 2px;
pointer-events: none;
}
.div-16__eyebrow {
font-size: 10.5px;
letter-spacing: .3em;
color: var(--div-16-mut);
}
.div-16__names {
font-family: Georgia,'Iowan Old Style',serif;
font-size: clamp(32px,7vw,62px);
line-height: 1.08;
font-weight: 400;
letter-spacing: .01em;
font-style: italic;
}
.div-16__amp {
color: var(--div-16-acc);
font-size: .72em;
padding: 0 .06em;
}
.div-16__rule {
width: 100%;
max-width: 320px;
display: flex;
align-items: center;
gap: 14px;
}
.div-16__rule::before,
.div-16__rule::after {
content: '';
flex: 1 1 0;
height: 1px;
}
.div-16__rule::before {
background: linear-gradient(90deg,transparent,var(--div-16-line) 88%);
}
.div-16__rule::after {
background: linear-gradient(90deg,var(--div-16-line) 12%,transparent);
}
.div-16__rule--short {
max-width: 180px;
}
.div-16__heart {
width: 17px;
height: 17px;
flex: none;
background: var(--div-16-acc);
clip-path: path('M8.5 15.6 1.9 9.1a4.1 4.1 0 1 1 6.6-4.7 4.1 4.1 0 1 1 6.6 4.7Z');
animation: div-16-beat 2.4s ease-in-out infinite;
}
@keyframes div-16-beat {
0%,
72%,
100% {
scale: 1;
}
80% {
scale: 1.04;
}
88% {
scale: 1;
}
}
.div-16__dot {
width: 5px;
height: 5px;
flex: none;
border-radius: 99px;
background: var(--div-16-acc);
opacity: .8;
}
.div-16__date {
font-size: 11.5px;
letter-spacing: .22em;
line-height: 2.2;
color: var(--div-16-mut);
}
.div-16__place {
font-family: Georgia,serif;
font-style: italic;
font-size: clamp(14px,1.9vw,17px);
color: var(--div-16-ink);
}
.div-16__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11px;
color: var(--div-16-mut);
padding: 8px 14px;
border: 1px solid var(--div-16-line);
border-radius: 99px;
}
@media (prefers-reduced-motion: reduce) {
.div-16__heart {
animation: none;
}
}
```Here's a working CSS Divider 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: Wedding Heart Icon Divider CSS
Source: https://codefronts.com/snippets/css-dividers/romantic-dividers/
An invitation-grade divider: two hairlines fading toward a centred heart, with the heart drawn by clip-path rather than an emoji — so it inherits your palette, scales cleanly, and never renders as someone else's cartoon glyph. A slow, tiny beat animation adds life without turning a wedding page into a toy, and the whole thing is one flex row.
## HTML
```html
<section class="div-16" aria-label="Wedding heart icon divider demo">
<div class="div-16__stage">
<div class="div-16__frame">
<p class="div-16__eyebrow">TOGETHER WITH THEIR FAMILIES</p>
<h2 class="div-16__names">Amara <span class="div-16__amp">&</span> Elias</h2>
<div class="div-16__rule" role="separator" aria-label="Divider">
<span class="div-16__heart" aria-hidden="true"></span>
</div>
<p class="div-16__date">SATURDAY, THE TWELFTH OF SEPTEMBER<br>TWO THOUSAND TWENTY-SEVEN</p>
<div class="div-16__rule div-16__rule--short" role="separator" aria-label="Divider">
<span class="div-16__dot" aria-hidden="true"></span>
</div>
<p class="div-16__place">The Old Orangery · Bath, England</p>
</div>
<p class="div-16__chip">clip-path:path() heart · inward-fading rules · 4% beat</p>
</div>
</section>
```
## CSS
```css
.div-16 {
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--div-16-bg);
--div-16-bg: oklch(0.975 0.012 30);
--div-16-card: oklch(1 0.004 30);
--div-16-ink: oklch(0.32 0.03 25);
--div-16-mut: oklch(0.56 0.03 25);
--div-16-line: oklch(0.32 0.03 25/.24);
--div-16-acc: oklch(0.68 0.11 18);
font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
color: var(--div-16-ink);
}
.div-16 *,
.div-16 *::before,
.div-16 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.div-16__stage {
min-height: 100svh;
display: grid;
place-content: center;
justify-items: center;
gap: 20px;
padding: clamp(24px,5vw,60px) clamp(20px,5vw,56px);
background: radial-gradient(100% 70% at 50% 0%,oklch(0.99 0.014 28),transparent);
}
.div-16__frame {
width: min(92vw,520px);
background: var(--div-16-card);
border: 1px solid var(--div-16-line);
border-radius: 4px;
padding: clamp(34px,6vw,62px) clamp(24px,5vw,52px);
text-align: center;
display: grid;
justify-items: center;
gap: clamp(16px,3vw,26px);
box-shadow: 0 20px 50px oklch(0.32 0.03 25/.09);
position: relative;
}
.div-16__frame::before {
content: '';
position: absolute;
inset: 9px;
border: 1px solid oklch(0.68 0.11 18/.3);
border-radius: 2px;
pointer-events: none;
}
.div-16__eyebrow {
font-size: 10.5px;
letter-spacing: .3em;
color: var(--div-16-mut);
}
.div-16__names {
font-family: Georgia,'Iowan Old Style',serif;
font-size: clamp(32px,7vw,62px);
line-height: 1.08;
font-weight: 400;
letter-spacing: .01em;
font-style: italic;
}
.div-16__amp {
color: var(--div-16-acc);
font-size: .72em;
padding: 0 .06em;
}
.div-16__rule {
width: 100%;
max-width: 320px;
display: flex;
align-items: center;
gap: 14px;
}
.div-16__rule::before,
.div-16__rule::after {
content: '';
flex: 1 1 0;
height: 1px;
}
.div-16__rule::before {
background: linear-gradient(90deg,transparent,var(--div-16-line) 88%);
}
.div-16__rule::after {
background: linear-gradient(90deg,var(--div-16-line) 12%,transparent);
}
.div-16__rule--short {
max-width: 180px;
}
.div-16__heart {
width: 17px;
height: 17px;
flex: none;
background: var(--div-16-acc);
clip-path: path('M8.5 15.6 1.9 9.1a4.1 4.1 0 1 1 6.6-4.7 4.1 4.1 0 1 1 6.6 4.7Z');
animation: div-16-beat 2.4s ease-in-out infinite;
}
@keyframes div-16-beat {
0%,
72%,
100% {
scale: 1;
}
80% {
scale: 1.04;
}
88% {
scale: 1;
}
}
.div-16__dot {
width: 5px;
height: 5px;
flex: none;
border-radius: 99px;
background: var(--div-16-acc);
opacity: .8;
}
.div-16__date {
font-size: 11.5px;
letter-spacing: .22em;
line-height: 2.2;
color: var(--div-16-mut);
}
.div-16__place {
font-family: Georgia,serif;
font-style: italic;
font-size: clamp(14px,1.9vw,17px);
color: var(--div-16-ink);
}
.div-16__chip {
font-family: ui-monospace,Menlo,Consolas,monospace;
font-size: 11px;
color: var(--div-16-mut);
padding: 8px 14px;
border: 1px solid var(--div-16-line);
border-radius: 99px;
}
@media (prefers-reduced-motion: reduce) {
.div-16__heart {
animation: none;
}
}
```How this works
The heart is a pure CSS shape, no font and no SVG:
.heart{ width:16px; aspect-ratio:1; background:var(--acc);
clip-path:path('M8 14.6 1.6 8.3a3.9 3.9 0 1 1 6.4-4.4 3.9 3.9 0 1 1 6.4 4.4Z'); }Using clip-path:path() keeps the shape in CSS where it can inherit a background — including a gradient or an image — which the ❤ emoji cannot. The older two-pseudo-element technique (two rounded squares rotated ±45°) still works and needs no path() support; it's in the customisation notes as the fallback.
The rules fade toward the heart rather than butting into it:
.rule::before{ background:linear-gradient(90deg,transparent,var(--line) 85%) }
.rule::after { background:linear-gradient(90deg,var(--line) 15%,transparent) }Symmetric fades pointing inward concentrate attention on the ornament; a flat rule pointing outward does the opposite. This is the same trick a calligrapher uses when tapering a flourish.
The beat is deliberately restrained — a 4% scale over 1.8s with a long rest, not a pulse. Anything stronger and the page starts feeling like a notification badge.
Make it yours
- No path() support: build the heart from
::beforeand::after— two 12×18px rounded blocks rotated -45° and 45° withborder-radius:50% 50% 0 0. - Other motifs: rings (two overlapping circles with
border), a monogram in a script face, or a small olive branch. The rule/fade structure never changes. - Colour: blush oklch(0.72 0.09 20), dusty rose oklch(0.66 0.1 15), sage oklch(0.68 0.06 145). Set
--acconce; heart, dots and script heading follow. - Ornate version: add a second, shorter rule below at 40% width with 30% opacity for a double-rule invitation border.
Gotchas — read before shipping
- Emoji hearts render differently on every platform and are announced by screen readers as 'red heart' — that's noise inside a decorative divider. Draw the shape instead.
clip-path:path()uses absolute user units, so the shape does NOT scale with the element. Size the element to the path, or usepolygon()with percentages for a fluid heart.- A beating heart is charming once and irritating on a long page. Limit the animation to hero-level dividers and always calm it under prefers-reduced-motion.
- If the divider separates real content sections, keep
role="separator"on the wrapper and aria-hidden on the heart — the mark is decoration, the break is meaning.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 113+ | 111+ |
clip-path:path() — Chrome 88, Safari 13.1, Firefox 97. Everything else (flex, gradients, keyframes) is universal; the two-pseudo-element heart fallback works back to IE9.