Bokeh effect for a website background
Soft discs of light, like a city seen through a lens focused on something close. How the bokeh effect works, a canvas starter you can paste and run, and the skill that builds a finished hero around it.
Free skills to start. Pro is $79 a year for every skill, or $9.99 a month for 10. See pricing
What is a bokeh effect?
Bokeh is what a camera lens does to lights that are out of focus: each point of light spreads into a soft disc the shape of the lens opening. Street lamps, fairy lights and lit windows behind a subject turn into overlapping circles of color.
On a website it gives depth and mood without detail that fights the copy. Warm amber discs feel like evening and hospitality, cold blue and cyan ones feel like a city at night, and pastel ones feel soft and calm. Because it is blurred by nature, text sits on it easily.
How the effect works
You do not need a real blur to fake bokeh. Draw each light as a filled circle with a soft edge (a radial gradient that is bright inside and falls off at the rim), at low opacity, and let overlapping circles add up. Additive blending, globalCompositeOperation = "lighter" on a canvas, makes overlaps brighten the way real light does.
Depth comes from size and speed. Big, faint discs feel close to the lens and drift a little; small, sharper ones feel far away. A slow drift and a gentle pulse in brightness are enough to keep it alive.
01
Pick a palette of lights
Two or three hues from your brand, plus white. Real bokeh rarely has more colors than the scene behind it.
02
Draw soft discs
A radial gradient from the color at 60–80% radius to transparent at the edge gives the lens-disc rim.
03
Add, do not cover
Use additive blending so overlaps glow brighter instead of stacking flat colors.
04
Drift slowly by depth
Bigger discs move a little faster than small ones. A few pixels per second is plenty.
HTML
A canvas bokeh background in plain JavaScript
Sixty soft discs drawn with additive blending, sized for sharp screens and still for reduced motion. Change COLORS to your palette.
<canvas id="bokeh" style="position:fixed;inset:0;width:100%;height:100%;background:#0b0d16"></canvas>
<script>
const canvas = document.getElementById('bokeh')
const g = canvas.getContext('2d')
const COLORS = ['255,190,110', '120,220,255', '255,120,170', '255,255,255']
const still = matchMedia('(prefers-reduced-motion: reduce)').matches
let w, h
function size() {
const dpr = Math.min(devicePixelRatio, 2)
w = canvas.width = innerWidth * dpr
h = canvas.height = innerHeight * dpr
}
size(); addEventListener('resize', size)
const lights = Array.from({ length: 60 }, () => {
const depth = Math.random() // 0 far, 1 near
return {
x: Math.random(), y: Math.random(), depth,
r: 0.01 + depth * 0.06, // share of the screen width
c: COLORS[Math.floor(Math.random() * COLORS.length)],
phase: Math.random() * 6.28,
}
})
function frame(t) {
const s = t / 1000
g.globalCompositeOperation = 'source-over'
g.fillStyle = '#0b0d16'; g.fillRect(0, 0, w, h)
g.globalCompositeOperation = 'lighter'
for (const l of lights) {
const x = ((l.x + (still ? 0 : s * 0.004 * (0.3 + l.depth))) % 1) * w
const y = l.y * h + Math.sin(s * 0.3 + l.phase) * 12
const r = l.r * w
const a = (0.12 + 0.18 * (1 - l.depth)) * (0.8 + 0.2 * Math.sin(s + l.phase))
const disc = g.createRadialGradient(x, y, 0, x, y, r)
disc.addColorStop(0, 'rgba(' + l.c + ',' + a * 0.6 + ')')
disc.addColorStop(0.75, 'rgba(' + l.c + ',' + a + ')')
disc.addColorStop(1, 'rgba(' + l.c + ',0)')
g.fillStyle = disc
g.beginPath(); g.arc(x, y, r, 0, Math.PI * 2); g.fill()
}
if (!still) requestAnimationFrame(frame)
}
requestAnimationFrame(frame)
</script>A starting point written for this page, free to use in your own projects. The skills below build the finished version with checks, fallbacks and a recorded video.
What to get right on a real page
01
Keep it out of focus
Sharp edges read as dots, not bokeh. Soften every disc, and keep the largest ones the faintest.
02
Darken behind the copy
Bright discs behind white text kill contrast. Put a soft dark gradient under the headline, or keep the lights to one side.
03
Use fewer, bigger lights
Forty to eighty discs look like a lens. Hundreds of small ones look like confetti.
04
Hold a still frame for reduced motion
Respect prefers-reduced-motion: show one finished frame instead of the loop. A visitor who turned motion off still gets the look.
Skills that build a bokeh effect
A finished hero built on the effect, with your colors, fonts, logo and words, and a 1080p video for launch posts.
- Rain on Glass HeroClaude CodeCodexCursor+3 more agents
Motion Heroes · Pro
Rain on Glass Hero
Animated WebGL hero · page + embed + 1080p video
A rainy night seen through a window: lit windows, sodium lamps, neon signs and cars beyond the glass are all turned to bokeh, while drops run down the pane in fits and starts and each one holds the city upside down like a tiny lens. The copy sits on the darker side of the pane and the loop repeats without a seam.
Worth knowing: The bokeh city is generated from a seed, not your own photo, and the live hero needs WebGL.
Needs: Node.js 18+, Chrome (or Chromium/Edge), and ffmpeg for the video
See what Rain on Glass Hero makes
Install
Build a bokeh effect with your agent
Each skill is a SKILL.md folder, so it installs the same way in Claude Code, Codex, Cursor and other agents. The example below uses Rain on Glass Hero; each skill page has its own prompt.
1. Paste the install prompt
Your agent runs the installer. The first time, it shows a sign-in link so you can approve it in the browser.
Install the "Rain on Glass Hero" skill from Lookbk (https://lookbk.dev/skills/rain-on-glass-hero). 1. Run: curl -fsSL https://lookbk.dev/cli.js | node - add rain-on-glass-hero 2. If it prints a sign-in link, show it to me. When I say I approved it, run the same command again. 3. When the install finishes, read the SKILL.md it installed and tell me what you need from me to make the first result.
Or run it in a terminal
curl -fsSL https://lookbk.dev/cli.js | node - add rain-on-glass-hero2. Start a new session
Agents load skills when a session starts. The installer writes the folder where your agent looks:
- Claude Code
- ~/.claude/skills/rain-on-glass-hero
- Codex
- ~/.agents/skills/rain-on-glass-hero
- Cursor
- ~/.agents/skills/rain-on-glass-hero
3. Ask for the result
Describe it in plain words, for example:
Build a Rain on Glass hero for Northlight Cinema's late shows: amber sodium lamps and cyan neon on a blue-black night, headline 'Rain outside. Films inside.', and record the video for the season trailer.
Another agent? Install a skill in any agent
FAQ
Questions
Still stuck? The guides cover installing, agents and licensing in more detail.
Read the guidesHow do I make a bokeh effect in CSS?
Stack a few absolutely positioned circles with radial-gradient backgrounds, blur them with filter: blur(), set mix-blend-mode: screen and drift them with slow keyframes. It works for a handful of lights; for dozens, canvas is lighter.
What makes bokeh look real?
Soft but defined rims, overlaps that brighten, colors taken from a believable scene, and a range of sizes that matches depth. Perfect, even, evenly spaced circles look fake.
Is a bokeh background heavy on phones?
Sixty gradient discs on a 2D canvas are light. Cap the device pixel ratio at 2 and stop the loop when the hero scrolls out of view.
Can I get the bokeh hero as a video?
Yes. Rain on Glass Hero records a seamless frame-exact 1080p MP4 of the loop, so the same scene works in posts and where scripts are not allowed.
