Fireflies
Eight CSS fireflies drift randomly on a dark background — three independent float animations crossed with a pulsating opacity glow, zero JavaScript.
You'll get access to the interactive demo with a free account.
This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Atmosphere has 57 effects, including 10 free. Explore the category →
3 usage examples



How it works
The effect relies on three float keyframes (fireflyFloat1, fireflyFloat2, fireflyFloat3) and one pulsation keyframe (fireflyGlow), all in pure CSS — no requestAnimationFrame, no DOM manipulation. Each float keyframe defines four waypoints (25 %, 50 %, 75 %, 100 %) with different translations (±10 to ±25 px in X and Y) to simulate natural, unpredictable flight.
Each .firefly runs two simultaneous animations: a drift animation (duration 5 s to 9 s, direction normal or reverse) and the pulsation (fireflyGlow — opacity 0.2 → 1 → 0.2, duration 1.5 s to 3 s with staggered animation-delay values from 0 to 1.2 s). Crossing different frequencies gives the impression that each firefly beats at its own rhythm.
The glow is achieved through a double box-shadow: an inner halo (rgba(255,255,170,.8) 0 0 6px 2px) and a diffuse outer halo (rgba(255,255,170,.4) 0 0 12px 4px) on a 4×4 px dot with border-radius: 50% and color #ffa. When opacity drops to 0.2 via fireflyGlow, the halo becomes nearly invisible — the firefly "blinks out".
Spatial placement is hardcoded in .firefly:nth-child(n) rules, each assigning its initial position (top/left as %), animation combination and durations. Adding a 9th firefly only requires a new :nth-child(9) rule — the keyframes are unchanged.
Accessibility
- prefers-reduced-motion not handled: the code contains no
@media (prefers-reduced-motion: reduce)block. Animations run even when the user has requested reduced motion. Add a CSS media query to disable or freeze animations if you deploy in an accessible context. - No ARIA attributes on the container or dots —
.fireflies-containerhas norole,aria-label, oraria-hidden. For a decorative use, addingaria-hidden="true"to the container is recommended. - The
.fireflydots are not focusable — no keyboard or mouse interaction is built in. The effect is purely decorative; no screen reader will navigate to these elements. - Contrast: the yellow glow (#ffa) on a dark background (#0a0f1a) is visible in normal vision. No text is embedded in the effect — text contrast depends on whatever overlay content you add.
- Animations loop indefinitely (
infinite) with no exposed pause mechanism. A complete implementation should include a pause button to meet WCAG 2.2.2.
Browser compatibility
Requires CSS Animations Level 1 (@keyframes, animation) and box-shadow — supported in all browsers since 2012. Zero JavaScript dependency.
Without CSS animation support, <code>.firefly</code> elements render as static yellow dots with their box-shadow halo. Visually coherent, no movement.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="demo-preview">
<div class="fireflies-container">
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
<div class="firefly"></div>
</div>
<!-- Optional overlay content -->
<span class="fireflies-label">Your text</span>
</div>
Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| .firefly { background } | #ffa | Color of the central firefly dot. Change to any hex or hsl value — update the box-shadow rgba channels consistently. |
| .firefly { box-shadow } | rgba(255,255,170,.8) 0 0 6px 2px, rgba(255,255,170,.4) 0 0 12px 4px | Double glow halo: first spread = tight inner glow, second = diffuse outer bloom. Increase radii (6px/12px) or opacities for a more intense effect. |
| .firefly { width / height } | 4px / 4px | Size of the light dot. Go up to 6–8 px for more visible fireflies on lighter backgrounds, down to 2 px for a delicate pointillist effect. |
| keyframes fireflyFloat1/2/3 (translate) | ±10 to ±25 px | Spatial drift amplitude. Double the values for wider, more dramatic flight; reduce to ±5 px for a nearly hovering, near-still effect. |
| .firefly:nth-child(n) { animation-duration } | 5 s – 9 s (float) | Drift cycle duration per firefly. Extend to 10–15 s for a meditative pace; shorten to 3–4 s for an energetic flicker. |
| keyframes fireflyGlow (opacity 50%) | 1 | Peak opacity at the glow's brightest point. Lower to 0.6 for a dimmer pulse; keep at 1 for maximum brightness. |
| .firefly:nth-child(n) { animation-duration } | 1.5 s – 3 s (glow) | Pulsation speed per firefly. Short values (< 1 s) → rapid flicker; long values (4–6 s) → slow, breathing glow. |
| Number of .firefly elements | 8 | Add <div class="firefly"></div> elements to the HTML and their matching :nth-child(n) CSS rules. Recommended pool: 5 (subtle) to 20 (dense). |
FAQ
@keyframes, animation, and box-shadow only. No scripts, no npm dependencies. Drop it into any project — framework or plain HTML — without touching your existing JS.background: #ffa in the .firefly rule and change the two rgba values in the box-shadow to match. For green fireflies, use background: #afffa0 and rgba(170,255,160,...).<div class="firefly"></div> elements in the HTML and write their CSS rules (.firefly:nth-child(9) { top: …; left: …; animation: … }). Reuse fireflyFloat1/2/3 with different durations so each new firefly has distinct behaviour.