A beautiful, performant animated starfield background inspired by real night sky photography. Features dense stars with natural brightness distribution, subtle twinkling, shooting stars with realistic varying speeds, parallax effects, and optional nebula clouds. Perfect for creating engaging hero sections, landing pages, or any web interface that needs a touch of cosmic elegance.
- π Realistic Star Distribution - 800+ stars with natural brightness (70% dim, 20% medium, 7% bright, 3% very bright with glow)
- β¨ Subtle Twinkling - Configurable twinkling effect that's not overdone
- π« Bright Star Glow - Very bright stars feature a beautiful radial glow effect
- βοΈ Varying Speed Meteors - Shooting stars with slow (40%), medium (40%), and fast (20%) speeds
- π¨ Star Color Variations - Subtle white, warm white, cool blue, and yellow tints
- π Parallax Effect - Mouse movement creates 3D depth illusion (NEW in v1.4.0)
- π Nebula Clouds - Optional atmospheric nebula clouds for extra depth (NEW in v1.4.0)
- π« Pulsating Stars - Bright stars gently pulse for added realism (NEW in v1.4.0)
- βΈοΈ Pause/Resume - Control animation playback (NEW in v1.4.0)
- π± Responsive - Automatically adapts to canvas/window size with consistent star density
- β‘ Lightweight - Pure vanilla JavaScript, no dependencies
- π― Easy Integration - Simple API, works with any framework
- π§ Backward Compatible - Still exports
ConstellationBackgroundfor existing users
- Parallax Effect - Move your mouse to see stars shift with depth perception
- Nebula Clouds - Optional colorful nebula clouds that drift slowly in the background
- Pulsating Stars - Bright stars now gently pulse for more realistic appearance
- Pause/Resume - New methods to control animation:
pause(),resume(),togglePause() - Paused Getter - Check animation state with the
pausedproperty - Static Version - Access version via
RealisticStarfield.version - Improved Performance - Smoother parallax interpolation
- Enhanced Options - New configuration options for all new features
- TypeScript Definitions - Type definitions included in dist
| Option | Type | Default | Description |
|---|---|---|---|
enableParallax |
boolean | true |
Enable parallax effect on mouse movement |
parallaxStrength |
number | 0.02 |
Strength of parallax effect (0-1) |
enableNebula |
boolean | false |
Enable nebula cloud background |
nebulaOpacity |
number | 0.15 |
Opacity of nebula clouds (0-1) |
nebulaColors |
array | ['#4a0080', '#000066', '#003366'] |
Colors for nebula clouds |
enablePulsate |
boolean | true |
Enable pulsating effect on bright stars |
// Pause the animation
starfield.pause();
// Resume the animation
starfield.resume();
// Toggle pause/resume (returns new pause state)
const isPaused = starfield.togglePause();
// Check if paused
if (starfield.paused) {
console.log('Animation is paused');
}
// Get version
console.log(RealisticStarfield.version); // "1.4.0"npm install my-constellation-bg# Build the package
npm run build
# Test the package (verify it works)
npm test<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Starfield Background</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
}
#starfield-canvas {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: -1;
}
.content {
position: relative;
z-index: 1;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
flex-direction: column;
}
h1 {
font-size: 4rem;
margin-bottom: 1rem;
}
</style>
</head>
<body>
<canvas id="starfield-canvas"></canvas>
<div class="content">
<h1>Welcome to My Site</h1>
<p>Beautiful starfield background β¨</p>
</div>
<script src="dist/index.js"></script>
<script>
const canvas = document.getElementById('starfield-canvas');
// Create starfield with default settings (recommended)
const starfield = new RealisticStarfield(canvas);
// OR with custom options (v1.4.0):
// const starfield = new RealisticStarfield(canvas, {
// starCount: 1000, // More stars
// backgroundColor: '#0a0a0a', // Slightly lighter black
// meteorInterval: 6000, // Meteor every 6 seconds
// meteorAngle: 40, // Steeper angle
// enableMeteors: true, // Enable shooting stars
// enableTwinkle: true, // Enable twinkling
// twinkleIntensity: 0.4, // Twinkle amount (0-1)
// enableParallax: true, // Enable parallax effect
// parallaxStrength: 0.03, // Parallax intensity
// enableNebula: true, // Enable nebula clouds
// nebulaOpacity: 0.2, // Nebula visibility
// enablePulsate: true // Pulsating bright stars
// });
// Trigger a meteor manually (e.g., on button click)
// starfield.triggerMeteor();
// Update options dynamically
// starfield.setOptions({ meteorInterval: 3000 });
// Pause/resume controls
// starfield.pause();
// starfield.resume();
// starfield.togglePause();
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<!-- Same styles as above -->
</head>
<body>
<canvas id="starfield-canvas"></canvas>
<div class="content">
<h1>Welcome</h1>
</div>
<script type="module">
import RealisticStarfield from './src/index.js';
// OR for backward compatibility:
// import { ConstellationBackground } from './src/index.js';
const canvas = document.getElementById('starfield-canvas');
const starfield = new RealisticStarfield(canvas);
</script>
</body>
</html>import React, { useEffect, useRef } from 'react';
import RealisticStarfield from 'my-constellation-bg';
function App() {
const canvasRef = useRef(null);
const starfieldRef = useRef(null);
useEffect(() => {
if (canvasRef.current) {
starfieldRef.current = new RealisticStarfield(canvasRef.current, {
starCount: 800,
meteorInterval: 8000
});
}
return () => {
if (starfieldRef.current) {
starfieldRef.current.destroy();
}
};
}, []);
return (
<div style={{ position: 'relative', width: '100vw', height: '100vh' }}>
<canvas
ref={canvasRef}
style={{
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: -1
}}
/>
<div style={{
position: 'relative',
zIndex: 1,
color: 'white',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
flexDirection: 'column'
}}>
<h1>Welcome to My App</h1>
<p>Built with React βοΈ</p>
</div>
</div>
);
}
export default App;// StarfieldCanvas.jsx
import React, { useEffect, useRef } from 'react';
import RealisticStarfield from 'my-constellation-bg';
const StarfieldCanvas = ({ options = {} }) => {
const canvasRef = useRef(null);
const starfieldRef = useRef(null);
useEffect(() => {
if (canvasRef.current && !starfieldRef.current) {
starfieldRef.current = new RealisticStarfield(
canvasRef.current,
options
);
}
return () => {
if (starfieldRef.current) {
starfieldRef.current.destroy();
starfieldRef.current = null;
}
};
}, [options]);
return (
<canvas
ref={canvasRef}
style={{
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: -1
}}
/>
);
};
export default StarfieldCanvas;Usage:
import StarfieldCanvas from './StarfieldCanvas';
function App() {
return (
<>
<StarfieldCanvas
options={{
starCount: 1000,
meteorInterval: 5000
}}
/>
<div className="content">
<h1>Your Content Here</h1>
</div>
</>
);
}<template>
<div class="container">
<canvas ref="canvasRef" class="starfield-canvas"></canvas>
<div class="content">
<h1>Welcome to Vue App</h1>
<p>Powered by Vue 3 π’</p>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import RealisticStarfield from 'my-constellation-bg';
const canvasRef = ref(null);
let starfield = null;
onMounted(() => {
if (canvasRef.value) {
starfield = new RealisticStarfield(canvasRef.value, {
starCount: 800,
meteorInterval: 8000
});
}
});
onBeforeUnmount(() => {
if (starfield) {
starfield.destroy();
}
});
</script>
<style scoped>
.container {
position: relative;
width: 100vw;
height: 100vh;
}
.starfield-canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.content {
position: relative;
z-index: 1;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
flex-direction: column;
}
h1 {
font-size: 3rem;
margin-bottom: 1rem;
}
</style><template>
<div class="container">
<canvas ref="canvas" class="starfield-canvas"></canvas>
<div class="content">
<h1>Your Content</h1>
</div>
</div>
</template>
<script>
import RealisticStarfield from 'my-constellation-bg';
export default {
data() {
return {
starfield: null
};
},
mounted() {
this.starfield = new RealisticStarfield(this.$refs.canvas, {
starCount: 800,
meteorInterval: 8000
});
},
beforeUnmount() {
if (this.starfield) {
this.starfield.destroy();
}
}
};
</script>
<style scoped>
.container {
position: relative;
width: 100vw;
height: 100vh;
}
.starfield-canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
.content {
position: relative;
z-index: 1;
color: white;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
flex-direction: column;
}
</style>Customize the appearance and behavior:
const starfield = new RealisticStarfield(canvas, {
starCount: 800, // Number of stars (scales with screen size)
backgroundColor: '#000000', // Pure black deep space
meteorInterval: 8000, // Time between meteors (ms)
meteorAngle: 35, // Meteor angle in degrees
enableMeteors: true, // Enable/disable shooting stars
enableTwinkle: true, // Enable/disable star twinkling
twinkleIntensity: 0.3 // Twinkle strength (0-1)
});| Option | Type | Default | Description |
|---|---|---|---|
starCount |
Number | 800 |
Base number of stars (auto-scales with screen size) |
backgroundColor |
String | '#000000' |
Canvas background color (pure black recommended) |
meteorInterval |
Number | 8000 |
Time between meteor spawns (milliseconds) |
meteorAngle |
Number | 35 |
Fixed angle for meteors in degrees (from vertical) |
enableMeteors |
Boolean | true |
Enable or disable shooting stars |
enableTwinkle |
Boolean | true |
Enable or disable star twinkling effect |
twinkleIntensity |
Number | 0.3 |
How much stars twinkle (0 = none, 1 = maximum) |
Meteors spawn with varying speeds for a realistic effect:
- 40% Slow Meteors - Graceful, long trails (speed: 2-3.5)
- 40% Medium Meteors - Balanced appearance (speed: 4-6)
- 20% Fast Meteors - Quick bright streaks (speed: 8-12)
Stars are distributed with realistic brightness levels:
- 70% Dim Stars - Tiny, faint (like distant stars)
- 20% Medium Stars - Moderate brightness
- 7% Bright Stars - Clearly visible
- 3% Very Bright Stars - With glow effect
// Just use defaults - they look like a real photo!
new RealisticStarfield(canvas);new RealisticStarfield(canvas, {
starCount: 1500, // More stars
meteorInterval: 5000 // More frequent meteors
});new RealisticStarfield(canvas, {
starCount: 400, // Fewer stars
meteorInterval: 15000, // Rare meteors
twinkleIntensity: 0.2 // Very subtle twinkle
});new RealisticStarfield(canvas, {
enableMeteors: false, // Disable shooting stars
enableTwinkle: true // Keep twinkling
});<style>
.hero {
position: relative;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
#hero-canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
</style>
<section class="hero">
<canvas id="hero-canvas"></canvas>
<div class="hero-content">
<h1>Your Hero Title</h1>
<p>Subtitle goes here</p>
</div>
</section>
<script src="dist/index.js"></script>
<script>
const canvas = document.getElementById('hero-canvas');
new RealisticStarfield(canvas);
</script><style>
body {
margin: 0;
background: #000;
}
#bg-canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
main {
position: relative;
z-index: 1;
min-height: 100vh;
color: white;
padding: 2rem;
}
</style>
<canvas id="bg-canvas"></canvas>
<main>
<h1>Page Title</h1>
<p>Your content scrolls normally while background stays fixed</p>
<!-- More content... -->
</main>
<script src="dist/index.js"></script>
<script>
const canvas = document.getElementById('bg-canvas');
new RealisticStarfield(canvas);
</script>new RealisticStarfield(canvas, options)
// OR for backward compatibility:
new ConstellationBackground(canvas, options)Creates a new starfield instance.
Parameters:
canvas(HTMLCanvasElement) - The canvas element to render onoptions(Object, optional) - Configuration object
Returns: RealisticStarfield instance
Stops the animation and cleans up event listeners. Always call this when removing the canvas (especially in SPAs).
starfield.destroy();Update options dynamically without recreating the instance.
starfield.setOptions({ meteorInterval: 5000 });Manually trigger a shooting star (e.g., on button click or event).
starfield.triggerMeteor();Manually trigger a resize. Usually called automatically on window resize.
starfield.resize();my-constellation-bg/
βββ dist/
β βββ index.js # Built file (after npm run build)
βββ src/
β βββ index.js # Source file (RealisticStarfield class)
βββ test.js # Test suite
βββ index.html # Demo page
βββ package.json
βββ README.md
- Z-index: Always set canvas
z-index: -1to keep it behind content - Fixed positioning: Use
position: fixedfor full-page backgrounds - Performance: Lower
starCountfor better mobile performance (try 100-150) - Cleanup: Always call
destroy()when unmounting (React/Vue components) - Responsive: Canvas automatically resizes, no additional code needed
- Build first: Run
npm run buildbefore using in production
Works in all modern browsers that support:
- Canvas API
- ES6 Classes
- RequestAnimationFrame
Tested on: Chrome, Firefox, Safari, Edge
- Landing page hero sections
- Login/signup page backgrounds
- Portfolio websites
- Dashboard backgrounds
- Loading screens
- Presentation slides
- Marketing pages
Major Update - Grok-style Improvements
- β¨ Fixed Position Stars: Stars now have anchor positions with subtle drift movement
- βοΈ Variable Speed Meteors: Added slow (30%), medium (50%), and fast (20%) meteor types
- π« Bright Star Glow: 15% of stars now feature a special radial glow effect
- π¨ Enhanced Meteor Colors: Different meteor speeds have unique color schemes
- βοΈ New Options: Added
starDriftanddriftSpeedconfiguration options - π Performance: Optimized animation loop for smoother rendering
- Bug fixes and stability improvements
- Initial public release with blinking stars, connections, and meteors
MIT Β© Anupam Raj
Contributions, issues, and feature requests are welcome!
Feel free to check (https://github.com/anupamraj176/my-constellation-bg).
If you like this project, please give it a β on GitHub!
Made with βοΈ by Anupam Raj