A string of camp bulbs where every bulb is tuned to a note. Click any one to play it. They use a pentatonic scale, which means no matter the order you press them — solo, melody, or mash all five — nothing ever sounds wrong.
A perfect "delight" element for personal sites, artist portfolios, kids sites, and product landing pages where you want one moment of joy. The pentatonic safeguard means even rapid mashing sounds intentional, never cacophonous.
Skip on anything that needs to feel serious or quiet (legal, medical, banking) and on sites where audio would break a user's flow. Web Audio is muted by default in modern browsers until first user gesture, so it won't surprise anyone — they have to click first.
A container with one .bulb per note. Each bulb declares its color + note frequency via CSS variable + data attribute.
<div class="xylo"> <div class="bulbs"> <div class="bulb" data-freq="262" style="--bulb-color:#ff4d8d"> <div class="bulb-body"></div> <span class="note-label">C</span> </div> <div class="bulb" data-freq="294" style="--bulb-color:#ff8a3d"> <div class="bulb-body"></div> <span class="note-label">D</span> </div> <!-- ... E (330), G (392), A (440) ... --> </div> </div>
Bulb shape with a teardrop radius + glow via box-shadow. The .playing class fires on click for the brighter pop.
.xylo { position: relative; padding-top: 30px; } .xylo::before { content: ""; position: absolute; top: 0; left: 5%; right: 5%; height: 60px; border-top: 1px solid rgba(243, 238, 221, .25); border-radius: 50% / 100%; } .bulbs { display: flex; gap: 40px; justify-content: center; } .bulb { position: relative; width: 30px; height: 46px; cursor: pointer; transition: transform .15s ease-out; } .bulb::before { /* wire cap */ content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: 8px; height: 6px; background: #2a2522; border-radius: 2px 2px 0 0; } .bulb-body { position: absolute; top: 6px; left: 0; width: 30px; height: 40px; border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%; background: var(--bulb-color); box-shadow: 0 0 14px var(--bulb-color); transition: filter .15s; } .bulb:hover .bulb-body { filter: brightness(1.3); } .bulb.playing { transform: translateY(4px) scale(1.18); } .bulb.playing .bulb-body { filter: brightness(1.8); }
Web Audio creates each note on the fly — no audio files needed. The envelope (attack/decay) makes it sound like a soft glockenspiel hit, not a beep.
// Swamp UI — Xylophone Lights (function () { let ctx = null; function note(freq, duration) { try { if (!ctx) ctx = new (window.AudioContext || window.webkitAudioContext)(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.connect(gain).connect(ctx.destination); osc.type = 'sine'; osc.frequency.setValueAtTime(freq, ctx.currentTime); // gentle chime envelope gain.gain.setValueAtTime(0, ctx.currentTime); gain.gain.linearRampToValueAtTime(0.18, ctx.currentTime + 0.02); gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + (duration || 0.6)); osc.start(); osc.stop(ctx.currentTime + (duration || 0.6)); } catch (e) {} } document.querySelectorAll('.bulb').forEach(bulb => { const freq = parseFloat(bulb.dataset.freq); bulb.addEventListener('click', () => { note(freq); bulb.classList.add('playing'); setTimeout(() => bulb.classList.remove('playing'), 300); }); }); })();
| Where | Default | Effect |
|---|---|---|
HTML data-freq |
261.6 (C4) | Frequency in Hz. Any number works. Use 1.5x for fifth, 2x for octave up. |
HTML --bulb-color (CSS var) |
var(--neon-pink) | Each bulb's color. Set inline per bulb to mix palettes. |
JS osc.type |
sine | Waveform. sine = clean. triangle = warm. sawtooth = sharp. |
| JS gain peak | 0.18 | Max loudness (0–1). Anything above 0.25 starts feeling rude. |
JS duration |
0.6 s | How long each note rings. Shorter = pluckier; longer = chime-y. |
A pentatonic scale uses 5 notes spaced so no combination produces dissonance. That means random clicks always sound musical. Three scales worth knowing:
| Scale | Notes (Hz) | Vibe |
|---|---|---|
Pentatonic C |
262, 294, 330, 392, 440 | Bright, happy — default. Folk / pop. |
Pentatonic A minor |
220, 262, 294, 330, 392 | Melancholy, thoughtful. Studio Ghibli energy. |
Wind chime |
523, 587, 698, 784, 880 | High, ethereal. Garden / temple feeling. |