Day/Night Cycle
Pure CSS animation: a sky gradient cycles through night, dawn, noon, and dusk while a glowing sun arcs from horizon to zenith — no JavaScript, no dependency.
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 two synchronized CSS @keyframes running in parallel at the same duration (12 s, ease-in-out infinite). .daynight-container fills the entire container (position: absolute; inset: 0) and animates its background property through five states: deep night (#0a0a2e), dawn/dusk (#e85d75 at bottom), golden morning (#f0c27f at bottom), full noon (#4aa3df at top), and back to night. The gradient is always vertical (linear-gradient, 3 stops); only the colors change at each keyframe.
The sun (.daynight-sun) is a 40 × 40 px div, colored gold with a double box-shadow (close halo 30 px + wide halo 60 px). @keyframes sunPath interpolates three properties: bottom (from −40 px to 80% at zenith, back to −40 px), left (50% → 30% at sunrise → 50% at zenith → 70% at sunset → 50%) and opacity (0 below the horizon, 1 once risen). This combination of coordinates traces a parabolic arc across the scene from left to right.
The native CSS ease-in-out easing smooths velocity at the extremes: the sun slows at dawn and dusk, accelerates toward zenith — no trigonometry in JavaScript. The shared 12 s duration guarantees perfect synchronization between sky and sun at every instant of the cycle, as both animations share the same animation-duration and animation-delay: 0s.
No JavaScript is used: no requestAnimationFrame, no canvas, no public API. The text label (.daynight-label) overlays via z-index: 2 and position: relative, staying in the normal DOM flow and readable by screen readers without additional aria attributes.
Accessibility
- prefers-reduced-motion not present in the code: the animation loops infinitely with no condition. Add manually:
@media (prefers-reduced-motion: reduce) { .daynight-container, .daynight-sun { animation: none; } }in your global stylesheet to freeze the scene at its initial state. - The
.demo-previewcontainer exposes neitherrolenoraria-labelin the base code: this is fine for decorative use. Addrole="img" aria-label="Animated day/night cycle"when the animation is part of semantic content. - The
.daynight-labeltext is a native<span>in the DOM flow, readable by screen readers without additionalariaattributes. - No keyboard or mouse interaction (entirely passive animation) — no focus management is required by the effect itself.
- Text contrast on the animated background: at the 50% keyframe (full day, light sky
#e0f0ff), white or light text may fall below the WCAG AA ratio (4.5:1). Add atext-shadowor a semi-transparent scrim if overlaying CTAs.
Browser compatibility
Uses CSS animation, linear-gradient, and box-shadow — supported in all modern browsers. Zero JavaScript dependency.
Without CSS animation support, <code>.daynight-container</code> stays in its initial state (dark blue <code>#0a0a2e</code>) and the sun remains below the horizon (<code>opacity: 0</code>) — the page stays functional, the effect is absent but no JS error is thrown.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="demo-preview" role="img" aria-label="Animated day/night cycle">
<div class="daynight-container" aria-hidden="true"></div>
<div class="daynight-sun" aria-hidden="true"></div>
<!-- Optional: overlay content -->
<span class="daynight-label">Day / Night Cycle</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 |
|---|---|---|
| animation-duration: 12s | 12s | Full cycle duration — change the value in both animation shorthands (on .daynight-container and .daynight-sun). 6 s = fast demo, 20–60 s = contemplative ambient. |
| Colors in @keyframes dayNightCycle | 5 palettes (night / dawn / morning / noon / dusk) | Replace hex values in each keyframe block to restyle the sky — e.g. #87ceeb → #00bcd4 for a tropical look, or darken all tones for an extended-night theme. |
| width/height on .daynight-sun | 40px | Sun disc diameter. 20 px for a compact widget, 60 px for an immersive full-screen scene. |
| box-shadow on .daynight-sun | gold 0 0 30px, rgba(255,215,0,.4) 0 0 60px | Halo intensity and color. Replace gold with #ff6a00 for a warm sunset glow, or #c8e6ff for a cold winter sun. |
| bottom: 80% (keyframe 50%) | 80% | Maximum sun height at zenith in @keyframes sunPath. 90% places the sun near the top edge, 55% keeps it low on the horizon. |
| left: 30% / 70% (keyframes 25% / 75%) | 30% / 70% | Horizontal positions of sunrise and sunset in @keyframes sunPath. 40%/60% for a more vertical arc, 15%/85% for a very wide sweep. |
| animation-delay (on both elements) | 0s | Cycle start offset on .daynight-container and .daynight-sun. Negative value: -6s begins at full noon, -3.6s at golden morning. In JS: el.style.animationDelay = '-' + offset + 's' applied to both elements. |
FAQ
@keyframes, zero external dependencies. It works in any static HTML environment (HTML email aside), without a bundler or framework.@media (prefers-reduced-motion: reduce) { .daynight-container, .daynight-sun { animation: none; } }. This freezes the scene at its initial state (dark blue night) without removing the elements.animation-delay: const s = new Date(); const offset = ((s.getHours()*3600 + s.getMinutes()*60 + s.getSeconds()) / 86400) * 12; [container, sun].forEach(el => el.style.animationDelay = '-' + offset + 's'); — the cycle stays entirely in CSS.