A lightweight, zero-dependency interactive dot grid background animation for the web. Dots are hidden by default and brighten / grow as the cursor approaches them.
- Zero runtime dependencies
- Drop-in background mode — never blocks clicks, hovers, selection, or scrolling
- Cursor stays visible (no
cursor: none) - Tiny: ~2 KB minified + gzipped
- TypeScript types included
- Works as ESM, CommonJS, or via a
<script>tag
npm install interactive-dot-gridOr use it directly from a CDN — no build step required:
<script src="https://unpkg.com/interactive-dot-grid"></script>
<script>
new InteractiveDotGrid.DotGrid();
</script>import { DotGrid } from 'interactive-dot-grid';
new DotGrid();That's it. The canvas mounts onto document.body as a fixed background. Your existing layout, links, buttons, and text all keep working — the canvas uses pointer-events: none, so it never intercepts anything.
import { DotGrid } from 'interactive-dot-grid';
const grid = new DotGrid({
container: document.getElementById('hero'),
spacing: 18,
color: '255,209,102',
});The container is automatically given position: relative if it doesn't already have a positioned ancestor.
All options are optional. Defaults shown below.
| Option | Type | Default | Description |
|---|---|---|---|
container |
HTMLElement |
document.body |
Where to mount the canvas. Omit for fullscreen-fixed background mode. |
spacing |
number |
22 |
Distance between dots in CSS pixels. |
dotMin |
number |
3 |
Idle dot radius. |
dotMax |
number |
12 |
Peak dot radius when the cursor is directly over a dot. |
radiusEffect |
number |
220 |
Cursor influence radius in pixels. |
baseAlpha |
number |
0 |
Idle alpha (0 = fully hidden). |
maxAlpha |
number |
0.85 |
Peak alpha when cursor is directly over a dot. |
color |
string |
"180,178,169" |
Dot color as r,g,b. |
smoothing |
number |
0.12 |
Per-frame interpolation factor (0–1). Higher = snappier transitions. |
zIndex |
number |
0 |
CSS z-index for the canvas. Use a negative value to push it behind everything. |
autoStart |
boolean |
true |
Start the animation immediately. |
const grid = new DotGrid(options);
grid.start(); // resume the animation loop
grid.stop(); // pause the animation loop
grid.setOptions({ ... }); // update options at runtime
grid.destroy(); // remove canvas, listeners, stop loopcreateDotGrid(options) is also exported as a functional alias for new DotGrid(options).
import { useEffect } from 'react';
import { DotGrid } from 'interactive-dot-grid';
export function Background() {
useEffect(() => {
const grid = new DotGrid();
return () => grid.destroy();
}, []);
return null;
}<script setup>
import { onMounted, onBeforeUnmount } from 'vue';
import { DotGrid } from 'interactive-dot-grid';
let grid;
onMounted(() => { grid = new DotGrid(); });
onBeforeUnmount(() => grid?.destroy());
</script><script>
import { onMount } from 'svelte';
import { DotGrid } from 'interactive-dot-grid';
onMount(() => {
const grid = new DotGrid();
return () => grid.destroy();
});
</script>The canvas is created with these styles:
position: fixed(orabsoluteinside a container)pointer-events: none— clicks, selection, scrolling all pass throughz-index: 0(configurable, set negative to put it behind all content)- No
cursor: none— the user's cursor stays visible everywhere
Make sure the elements you want to appear above the dots have position: relative (or any non-static positioning) so their stacking context wins.
npm install
npm run build # writes ESM, CJS, IIFE, and .d.ts to dist/
npm run dev # rebuild on file changes
npm run demo # build and open demo/index.html in a local serverMIT