A dark honeycomb whose lines light up as a soft glow wanders underneath, while a few cells fill and fade. The hex lines are one SVG tile used as a mask, so the glow only shows through them.
Also known as: honeycomb background css, hexagon pattern animation, animated hexagon grid.
<div class="bgx-hexagon-pulse" aria-hidden="true"> <span class="bgx-hexagon-pulse-lit"><i></i></span> <span class="bgx-hexagon-pulse-cell" style="--x: 14%; --y: 25%; --d: 0s"></span> <span class="bgx-hexagon-pulse-cell" style="--x: 38%; --y: 75%; --d: -1.2s"></span> <span class="bgx-hexagon-pulse-cell" style="--x: 57%; --y: 25%; --d: -2.6s"></span> <span class="bgx-hexagon-pulse-cell" style="--x: 78%; --y: 75%; --d: -3.5s"></span> <span class="bgx-hexagon-pulse-cell" style="--x: 92%; --y: 25%; --d: -0.6s"></span> </div>
.bgx-hexagon-pulse {
--c: var(--bgx-color, #3b82f6);
font-size: var(--bgx-size, 16px);
position: absolute;
inset: 0;
overflow: hidden;
--w: 2.0785em;
--hh: 3.6em;
--hex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17.32 30' preserveAspectRatio='none'%3E%3Cpath d='M0 0V5L8.66 10L17.32 5V0M8.66 10V20M0 30V25L8.66 20L17.32 25V30' fill='none' stroke='%23000' stroke-width='1.1'/%3E%3C/svg%3E") 0 0 / var(--w) var(--hh);
container-type: size;
background: color-mix(in srgb, var(--c) 7%, #06080d);
}
.bgx-hexagon-pulse::before,
.bgx-hexagon-pulse-lit {
content: "";
position: absolute;
inset: 0;
-webkit-mask: var(--hex);
mask: var(--hex);
}
.bgx-hexagon-pulse::before {
background: color-mix(in srgb, var(--c) 18%, transparent);
}
.bgx-hexagon-pulse-lit > i {
position: absolute;
top: 0;
left: 0;
width: 18em;
height: 18em;
margin: -9em 0 0 -9em;
background: radial-gradient(closest-side, var(--c), color-mix(in srgb, var(--c) 40%, transparent) 45%, transparent);
animation:
bgx-hexagon-pulse-x 7s ease-in-out infinite alternate,
bgx-hexagon-pulse-y 4.3s ease-in-out infinite alternate;
}
.bgx-hexagon-pulse-cell {
position: absolute;
width: var(--w);
height: 2.4em;
left: var(--x);
left: round(nearest, var(--x), var(--w));
top: calc(var(--y) - 1.2em);
top: calc(round(nearest, var(--y), var(--hh)) - 1.2em);
background: radial-gradient(circle, color-mix(in srgb, var(--c) 70%, transparent), color-mix(in srgb, var(--c) 25%, transparent));
clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
opacity: 0;
transform: scale(0.84);
animation: bgx-hexagon-pulse-fill 4.8s ease-in-out var(--d) infinite;
}
@keyframes bgx-hexagon-pulse-x {
from { translate: 8cqw 0; }
to { translate: 92cqw 0; }
}
@keyframes bgx-hexagon-pulse-y {
from { transform: translateY(10cqh); }
to { transform: translateY(90cqh); }
}
@keyframes bgx-hexagon-pulse-fill {
0%, 100% { opacity: 0; transform: scale(0.6); }
30% { opacity: 1; transform: scale(0.84); }
60% { opacity: 0; transform: scale(0.84); }
}
@media (prefers-reduced-motion: reduce) {
.bgx-hexagon-pulse, .bgx-hexagon-pulse *, .bgx-hexagon-pulse::before, .bgx-hexagon-pulse::after, .bgx-hexagon-pulse *::before, .bgx-hexagon-pulse *::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.