Hearts in three shades rise from the bottom of a blush backdrop, swaying, beating and fading out near the top. Each heart is four gradients on one pseudo-element, no clip-path or SVG.
Also known as: floating hearts css, valentine background css, hearts animation background.
<div class="bgx-floating-hearts" aria-hidden="true"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
.bgx-floating-hearts {
--c: var(--bgx-color, #3b82f6);
font-size: var(--bgx-size, 16px);
position: absolute;
inset: 0;
overflow: hidden;
--heart: color-mix(in oklab, var(--c) 25%, #ff4f8b);
background: linear-gradient(to top, color-mix(in srgb, var(--heart) 20%, #fff), color-mix(in srgb, var(--c) 4%, #fff));}
.bgx-floating-hearts span {
position: absolute;
top: 0;
left: var(--x);
height: 100%;
animation: bgx-floating-hearts-rise var(--dur) linear var(--delay) infinite;
}
.bgx-floating-hearts span::before {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: var(--s);
height: var(--s);
background:
radial-gradient(circle at 60% 65%, var(--k) 64%, transparent 65%) top left / 51% 51%,
radial-gradient(circle at 40% 65%, var(--k) 64%, transparent 65%) top right / 51% 51%,
linear-gradient(to bottom left, var(--k) 43%, transparent 43%) bottom left / 51% 51%,
linear-gradient(to bottom right, var(--k) 43%, transparent 43%) bottom right / 51% 51%;
background-repeat: no-repeat;
opacity: 0;
animation:
bgx-floating-hearts-sway var(--sway) ease-in-out var(--delay) infinite alternate,
bgx-floating-hearts-beat 1.6s ease-in-out var(--delay) infinite,
bgx-floating-hearts-fade var(--dur) linear var(--delay) infinite;
}
.bgx-floating-hearts span:nth-child(3n + 1) { --k: var(--heart); }
.bgx-floating-hearts span:nth-child(3n + 2) { --k: color-mix(in srgb, var(--heart) 55%, #fff); }
.bgx-floating-hearts span:nth-child(3n) { --k: color-mix(in oklab, var(--heart), var(--c) 45%); }
.bgx-floating-hearts span:nth-child(1) { --x: 40.8%; --s: 1.86em; --dur: 6.34s; --delay: -9.06s; --sway: 1.74s; }
.bgx-floating-hearts span:nth-child(2) { --x: 70.3%; --s: 0.94em; --dur: 8.45s; --delay: -1.48s; --sway: 1.97s; }
.bgx-floating-hearts span:nth-child(3) { --x: 10.7%; --s: 1.91em; --dur: 6.85s; --delay: -7.36s; --sway: 1.63s; }
.bgx-floating-hearts span:nth-child(4) { --x: 91.5%; --s: 1.47em; --dur: 6.5s; --delay: -8.63s; --sway: 2.17s; }
.bgx-floating-hearts span:nth-child(5) { --x: 86.4%; --s: 1.33em; --dur: 9.95s; --delay: -5.71s; --sway: 1.61s; }
.bgx-floating-hearts span:nth-child(6) { --x: 36.3%; --s: 1.13em; --dur: 9.36s; --delay: -1.59s; --sway: 2.27s; }
.bgx-floating-hearts span:nth-child(7) { --x: 16.5%; --s: 1.01em; --dur: 9.02s; --delay: -9.04s; --sway: 1.92s; }
.bgx-floating-hearts span:nth-child(8) { --x: 97.8%; --s: 1.36em; --dur: 7.75s; --delay: -5s; --sway: 2.03s; }
.bgx-floating-hearts span:nth-child(9) { --x: 51.5%; --s: 1.82em; --dur: 7.06s; --delay: -3.95s; --sway: 2.1s; }
.bgx-floating-hearts span:nth-child(10) { --x: 45.4%; --s: 1.67em; --dur: 9.66s; --delay: -4.58s; --sway: 2.06s; }
.bgx-floating-hearts span:nth-child(11) { --x: 79.7%; --s: 0.95em; --dur: 8.35s; --delay: -8.44s; --sway: 2.78s; }
.bgx-floating-hearts span:nth-child(12) { --x: 29%; --s: 0.92em; --dur: 6.36s; --delay: -6.45s; --sway: 2.27s; }
.bgx-floating-hearts span:nth-child(13) { --x: 23.5%; --s: 0.81em; --dur: 8.29s; --delay: -3.7s; --sway: 2.47s; }
.bgx-floating-hearts span:nth-child(14) { --x: 64.9%; --s: 1.97em; --dur: 7.2s; --delay: -5.71s; --sway: 1.95s; }
.bgx-floating-hearts span:nth-child(15) { --x: 59.8%; --s: 1.42em; --dur: 8.35s; --delay: -8.53s; --sway: 2.56s; }
.bgx-floating-hearts span:nth-child(16) { --x: 1.8%; --s: 0.82em; --dur: 6.5s; --delay: -0.97s; --sway: 1.83s; }
@keyframes bgx-floating-hearts-rise {
from { transform: translateY(var(--s)); }
to { transform: translateY(-100%); }
}
@keyframes bgx-floating-hearts-sway {
from { translate: -0.8em 0; rotate: -12deg; }
to { translate: 0.8em 0; rotate: 12deg; }
}
@keyframes bgx-floating-hearts-beat {
0%, 30%, 100% { transform: scale(1); }
12% { transform: scale(1.16); }
22% { transform: scale(1.06); }
}
@keyframes bgx-floating-hearts-fade {
0% { opacity: 0; }
10% { opacity: 0.9; }
65% { opacity: 0.9; }
90% { opacity: 0; }
100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
.bgx-floating-hearts, .bgx-floating-hearts *, .bgx-floating-hearts::before, .bgx-floating-hearts::after, .bgx-floating-hearts *::before, .bgx-floating-hearts *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--bgx-color on the element or a parent.
Currently previewing #3b82f6.--bgx-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.