Atmosphere✨ Premium

Dust Motes

Ten golden dust particles drift through an oblique light beam — pure CSS animation, no JavaScript, staggered durations and delays for organic, independent movement.

CSSAnimationParticles

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

Hero / Landing — Creative studio or dark portfolio — Dust Motes example 1

① Hero / Landing — Creative studio or dark portfolio

WhenHomepage of a photo studio, music label, or dark-theme creative agency seeking a cinematic, enveloping atmosphere.
WhyMotes build atmospheric depth without drawing attention — the visitor feels the mood before reading the headline. The absence of JavaScript simplifies integration into CMS or static-site generators.
SettingsMotes in rgba(200,170,100,.6) for a more discreet gold; beam width:160px, rotate(12deg) to sweep more of the scene; durations 9–14 s for cinematic slowness.
Product component — 'Processing' loading card — Dust Motes example 2

② Product component — 'Processing' loading card

WhenBackground indicator on a long-running loading state — file analysis, audio transcription, AI generation — where a spinner would be too intrusive.
WhyThe subtle motion signals that 'something is happening' without being aggressive. The CSS animation requires no server-side code, simplifying loading state in a React or Web Component.
SettingsMotes in rgba(180,190,255,.45) for a neutral blue tint; beam rgba(200,210,255,.05); durations 10–16 s for a slow, non-distracting rhythm.
Conversion micro-interaction — 'Access granted' screen — Dust Motes example 3

③ Conversion micro-interaction — 'Access granted' screen

WhenSign-up confirmation or email validation — the user has just gained access to a tool, members area, or premium product.
WhyThe luminous dust beam atmosphere evokes discovery and clarity. More intimate than confetti, more lasting than a spinner — the background keeps breathing while the user reads the message.
SettingsMotes in rgba(255,255,200,.85); more intense beam (rgba(255,255,150,.14), width:180px); faster durations 4–7 s for a slight dynamism on display.

How it works

The effect relies entirely on three CSS @keyframes (dustFloat1, dustFloat2, dustFloat3) applied to ten circular <div class="dust-mote"> elements (1–3 px, border-radius:50%). Each keyframe defines 4 waypoints (0%, 25%, 50%, 75%) with offset X/Y translations (±3–8 px horizontally, −5 to −30 px vertically) and opacity shifts (0.3–0.9). The ease-in-out timing decelerates at both ends of each segment, mimicking the real inertia of airborne particles.

Trajectory diversity comes entirely from CSS: each .dust-mote:nth-child(N) rule assigns a different duration (6–10 s) and a staggered delay (0–3 s). This desynchronisation breaks the repeating pattern and creates the illusion of independent motion. No values are drawn randomly at runtime — variety is entirely baked into static rules.

The light beam is an absolutely-positioned <div class="dust-beam"> (top:−20%; right:10%; width:120px; height:140%) with a linear-gradient from rgba(255,220,150,.08) to transparent, rotated 15° from transform-origin:right top. The contrast between this golden veil and the dark background (#1a1a2e → #16213e) produces the light-cutting-through-darkness effect.

With no JavaScript, no requestAnimationFrame, and no canvas, the browser's animation engine handles everything via GPU compositing. Motes are position:absolute with fixed px dimensions: they don't affect layout and trigger no reflow. Performance impact is negligible even on mobile.

Accessibility

  • No prefers-reduced-motion handling in the delivered code: CSS animations run regardless of system preference. For accessible integrations, add @media (prefers-reduced-motion: reduce) { .dust-mote { animation: none; } .dust-beam { opacity: 0.5; } }.
  • The .dust-container carries no role, aria-label, or aria-hidden. Since the effect is purely decorative, add aria-hidden="true" to the wrapper to exclude it from the accessibility tree.
  • No keyboard or mouse interaction is exposed: no clickable area, no focus trap. Overlay content must remain outside .dust-container to stay tabbable.
  • Mote color: rgba(255,220,150,.7) on a dark background — clearly visible (contrast > 4.5:1 in normal mode) but, being a non-text decorative element, WCAG 1.4.11 does not apply.
  • The container background can be removed when overlaying the effect on an existing page — add pointer-events:none so neither motes nor the beam capture clicks.

Browser compatibility

Requires CSS @keyframes and the animation property — available since Chrome 43, Firefox 16, Safari 9. No JavaScript dependency.

Chrome 43+✓ Full
Firefox 16+✓ Full
Safari 9+✓ Full
Edge 79+✓ Full
Mobile iOS 9+✓ Full
Android Chrome✓ Full

Without CSS animation support (browsers before 2015), motes remain static at their initial positions with their starting opacity — no errors, the effect degrades to a static background.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="dust-container" aria-hidden="true">
  <div class="dust-beam"></div>
  <div class="dust-mote"></div>
  <div class="dust-mote"></div>
  <div class="dust-mote"></div>
  <div class="dust-mote"></div>
  <div class="dust-mote"></div>
  <div class="dust-mote"></div>
  <div class="dust-mote"></div>
  <div class="dust-mote"></div>
  <div class="dust-mote"></div>
  <div class="dust-mote"></div>
</div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
.dust-mote { background } rgba(255, 220, 150, .7) Mote color and opacity — change the hue (e.g. blue rgba(150,190,255,.7)) to match your palette without touching the keyframes.
.dust-beam { background } (first stop) rgba(255, 220, 150, .08) Beam intensity and color — raise to .16 for a clearly visible beam, lower to .04 for subtle.
.dust-beam { width } 120px Beam width — 80 px for a fine shaft of light, 200 px for a broad luminous wash across the scene.
.dust-beam { transform: rotate(Ndeg) } 15deg Beam angle from transform-origin:right top — 0° = vertical drop, 45° = pronounced diagonal.
.dust-mote:nth-child(N) { animation-duration } 6s – 10s (per nth-child) Individual speed per mote — low values (3–5 s) = turbulent dust, high values (12–18 s) = atmospheric slowness.
.dust-mote:nth-child(N) { width / height } 1px – 3px (per nth-child) Individual mote size — stay under 6 px to keep the 'dust grain' look; larger values give bokeh-style particles.
.dust-container { background } linear-gradient(135deg, #1a1a2e 0, #16213e 100%) Scene background color — remove the property or set background:transparent to overlay the effect on your own background (also add pointer-events:none).

FAQ

Yes — it is pure CSS, no JavaScript. Drop the HTML into any component and the styles into the global or scoped CSS file. No initialisation, no lifecycle hooks, no dependencies to install.
Add a <div class="dust-mote"></div> inside .dust-container, then write a .dust-mote:nth-child(N) rule with a unique position (top/left), size (width/height), and animation (dustFloat1, dustFloat2, or dustFloat3) with a distinct duration and delay. To remove one, delete its div and matching nth-child rule.
Yes: make .dust-container position:absolute; inset:0 inside a position:relative parent, add pointer-events:none to the container, then place your content in a sibling with position:relative; z-index:1. The content stays interactive and accessible.