Vanilla JavaScript sky backgrounds with atmospheric scattering and a night starfield, driven by time and location.
Embed a living day-to-night sky: blue midday, warm twilight, and stars after dark — all from a Date and coordinates.
- Atmospheric scattering — Physically based single-scattering sky gradient
- Night starfield — Multi-layer stars with twilight fade and day-cycle rotation
- Time-driven — Call
updateSky(date)whenever your UI changes time - Location — Auto-detect via IP, or set latitude / longitude yourself
- One script — CSS injected automatically; SunCalc loaded from jsDelivr if missing
<script src="https://cdn.jsdelivr.net/gh/aakaashjois/dynamic-sky@main/dynamic-sky.js"></script>Also on npm via jsDelivr: https://cdn.jsdelivr.net/npm/dynamic-sky@2/dynamic-sky.js
Star/layer CSS is injected when the library loads. If SunCalc is not already on the page,
init()loadssuncalc@2.0.1from jsDelivr (/+esm).
<script src="path/to/dynamic-sky.js"></script>Optional explicit SunCalc:
<script type="module">
import * as SunCalc from 'https://cdn.jsdelivr.net/npm/suncalc@2.0.1/+esm';
window.SunCalc = SunCalc;
</script><!DOCTYPE html>
<html>
<body>
<div id="background-sky"></div>
<div id="stars-container"></div>
<div id="page-container">
<h1>Hello World</h1>
</div>
<script src="dynamic-sky.js"></script>
<script>
const sky = new DynamicSky();
sky.init();
</script>
</body>
</html>If the sky/star containers are missing, init() creates them. You can also pass selectors and location up front:
const sky = new DynamicSky({
skyContainer: '#background-sky',
starsContainer: '#stars-container',
latitude: 37.7749,
longitude: -122.4194,
starLayers: 3,
starDensity: 5
});
sky.init();Wire any control to a Date and call updateSky:
<input type="range" id="time" min="0" max="1440" value="0">
<script>
const sky = new DynamicSky();
sky.init().then(() => {
const time = document.getElementById('time');
const paint = () => sky.updateSky(sky.minutesToDate(parseInt(time.value, 10)));
time.addEventListener('input', paint);
time.value = sky.dateToMinutes();
paint();
});
</script>| Option | Type | Default | Description |
|---|---|---|---|
skyContainer |
string |
'#background-sky' |
CSS selector for sky background |
starsContainer |
string |
'#stars-container' |
CSS selector for stars |
latitude |
number |
null |
Latitude (auto-detected if omitted) |
longitude |
number |
null |
Longitude (auto-detected if omitted) |
autoDetectLocation |
boolean |
true |
Detect location via IP when coords are missing |
starLayers |
number |
3 |
Starfield layers (0–5) |
starDensity |
number |
5 |
Star density multiplier (0–20) |
Initialize the instance (loads SunCalc if needed, resolves location, paints the sky).
const sky = new DynamicSky();
sky.init();Paint the sky for a date/time. Omit date to use now.
sky.updateSky();
sky.updateSky(new Date('2024-12-25T12:00:00'));Set coordinates. Call updateSky(...) afterward to repaint.
sky.setLocation(40.7128, -74.0060);
sky.updateSky();Optional converters when your UI works in minutes of day (0–1440):
sky.updateSky(sky.minutesToDate(720)); // noon
const minutes = sky.dateToMinutes(); // now → minutesFor percent or hours: sky.minutesToDate(Math.round(percent * 1440)) or sky.minutesToDate(Math.round(hours * 60)).
Stars appear during twilight and night (sun below the horizon), rotate with the day cycle when you call updateSky(), and use a light CSS depth pulse on each layer. They are atmospheric craft, not an astronomical catalog. Density is reduced slightly on smaller viewports.
CSS hooks you can style: .dynamic-sky-layer, .dynamic-sky-star.
Modern Chromium, Firefox, Safari, and Edge. No IE11.
Copyright 2025 Aakaash Jois
Licensed under the Apache License 2.0 — see LICENSE.
- Horizon by dnlzro — original inspiration for location-based CSS sky gradients
- SunCalc by mourner — sun position
Made with care by aakaashjois