Clusters of linked dots drift and turn over a dark field while their links fade in and out, a pure CSS take on particles.js. Each cluster is one span: nodes in box-shadow, links in gradients.
Also known as: particles.js background css, connected dots background, plexus background css.
<div class="bgx-particle-network" aria-hidden="true"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
.bgx-particle-network {
--c: var(--bgx-color, #3b82f6);
font-size: var(--bgx-size, 16px);
position: absolute;
inset: 0;
overflow: hidden;
--dot: color-mix(in srgb, var(--c) 45%, #fff);
--link: color-mix(in srgb, var(--c) 60%, transparent);
background: radial-gradient(ellipse 90% 80% at 30% 20%, color-mix(in srgb, var(--c) 24%, #0b1022), #05070f 80%);}
.bgx-particle-network::before {
content: "";
position: absolute;
inset: 0 0 -12em;
background-size: 12em 12em;
background-image:
radial-gradient(circle 0.1em at 4.1% 78.4%, color-mix(in srgb, var(--c) 40%, #fff) 50%, transparent),
radial-gradient(circle 0.1em at 74.3% 5.4%, color-mix(in srgb, var(--c) 40%, #fff) 50%, transparent),
radial-gradient(circle 0.1em at 43.6% 62.1%, color-mix(in srgb, var(--c) 40%, #fff) 50%, transparent),
radial-gradient(circle 0.1em at 51.4% 84.5%, color-mix(in srgb, var(--c) 40%, #fff) 50%, transparent),
radial-gradient(circle 0.1em at 91.6% 20.5%, color-mix(in srgb, var(--c) 40%, #fff) 50%, transparent),
radial-gradient(circle 0.1em at 42.1% 5.3%, color-mix(in srgb, var(--c) 40%, #fff) 50%, transparent),
radial-gradient(circle 0.1em at 41.2% 27.7%, color-mix(in srgb, var(--c) 40%, #fff) 50%, transparent),
radial-gradient(circle 0.1em at 66.2% 84.6%, color-mix(in srgb, var(--c) 40%, #fff) 50%, transparent),
radial-gradient(circle 0.1em at 48% 40.2%, color-mix(in srgb, var(--c) 40%, #fff) 50%, transparent);
opacity: 0.6;
animation: bgx-particle-network-dust 30s linear infinite;
}
.bgx-particle-network span {
position: absolute;
top: var(--y);
left: var(--x);
width: var(--w);
height: var(--h);
rotate: var(--r);
animation: bgx-particle-network-drift var(--dur) ease-in-out var(--delay) infinite alternate;
}
.bgx-particle-network span::before {
content: "";
position: absolute;
top: -0.15em;
left: -0.15em;
width: 0.3em;
height: 0.3em;
border-radius: 50%;
background: var(--dot);
box-shadow: var(--w) 0 var(--dot), 0 var(--h) var(--dot);
}
.bgx-particle-network span::after {
content: "";
position: absolute;
inset: 0;
background:
linear-gradient(var(--link), var(--link)) 0 -0.03em / 100% 0.06em no-repeat,
linear-gradient(var(--link), var(--link)) -0.03em 0 / 0.06em 100% no-repeat,
linear-gradient(to bottom right, transparent calc(50% - 0.035em), var(--link) 0 calc(50% + 0.035em), transparent 0);
animation: bgx-particle-network-link var(--pulse) ease-in-out var(--delay) infinite;
}
.bgx-particle-network span:nth-child(1) { --x: 95.2%; --y: 23.4%; --w: 3.63em; --h: 3.71em; --r: 217deg; --dx: -1.44em; --dy: -0.98em; --turn: -16deg; --dur: 9.35s; --pulse: 3.7s; --delay: -7.67s; }
.bgx-particle-network span:nth-child(2) { --x: 76.7%; --y: 18.8%; --w: 4.48em; --h: 3.71em; --r: 222deg; --dx: 0.72em; --dy: 0.2em; --turn: 20deg; --dur: 9.28s; --pulse: 5.78s; --delay: -8.71s; }
.bgx-particle-network span:nth-child(3) { --x: 85.6%; --y: 16%; --w: 3.2em; --h: 3.42em; --r: 249deg; --dx: 1.67em; --dy: -0.08em; --turn: -11deg; --dur: 10.9s; --pulse: 3.55s; --delay: -6.67s; }
.bgx-particle-network span:nth-child(4) { --x: 31.7%; --y: 63.2%; --w: 4.32em; --h: 4.12em; --r: 231deg; --dx: 2.4em; --dy: -1.24em; --turn: -7deg; --dur: 9s; --pulse: 3.74s; --delay: -4.15s; }
.bgx-particle-network span:nth-child(5) { --x: 55.1%; --y: 46.4%; --w: 5.41em; --h: 4.22em; --r: 163deg; --dx: 0.79em; --dy: 0.2em; --turn: 14deg; --dur: 8.82s; --pulse: 4.84s; --delay: -9.35s; }
.bgx-particle-network span:nth-child(6) { --x: 64.6%; --y: 29.7%; --w: 5.5em; --h: 2.79em; --r: 8deg; --dx: -2.07em; --dy: 0.41em; --turn: -6deg; --dur: 11.61s; --pulse: 4.62s; --delay: -1.82s; }
.bgx-particle-network span:nth-child(7) { --x: 46.5%; --y: 53.1%; --w: 4.7em; --h: 3.08em; --r: 39deg; --dx: -1.93em; --dy: 1.33em; --turn: -23deg; --dur: 9.47s; --pulse: 5.51s; --delay: -2.43s; }
.bgx-particle-network span:nth-child(8) { --x: 25.8%; --y: 42.3%; --w: 5.69em; --h: 3.72em; --r: 194deg; --dx: 0.04em; --dy: -1.37em; --turn: -23deg; --dur: 11.51s; --pulse: 4.75s; --delay: -7.07s; }
.bgx-particle-network span:nth-child(9) { --x: 16.6%; --y: 35.3%; --w: 4.02em; --h: 3.5em; --r: 134deg; --dx: 1.79em; --dy: -1.32em; --turn: -7deg; --dur: 7.93s; --pulse: 3.78s; --delay: -3.13s; }
.bgx-particle-network span:nth-child(10) { --x: 2.1%; --y: 21%; --w: 4.42em; --h: 4.22em; --r: 333deg; --dx: -1.85em; --dy: -0.46em; --turn: 16deg; --dur: 9.58s; --pulse: 4.91s; --delay: -5.1s; }
@keyframes bgx-particle-network-drift {
from { transform: translate(0, 0) rotate(0deg); }
to { transform: translate(var(--dx), var(--dy)) rotate(var(--turn)); }
}
@keyframes bgx-particle-network-link {
0%, 100% { opacity: 0.15; }
50% { opacity: 1; }
}
@keyframes bgx-particle-network-dust {
to { transform: translateY(-12em); }
}
@media (prefers-reduced-motion: reduce) {
.bgx-particle-network, .bgx-particle-network *, .bgx-particle-network::before, .bgx-particle-network::after, .bgx-particle-network *::before, .bgx-particle-network *::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.