UI sound

인터페이스 사운드

A short sound tied to a single interaction — a tap, toggle, or swipe — that lets your ears confirm what your finger just did.

Also known as: Interaction soundFeedback soundClick sound
···
html
<div class="wrap">
  <div class="row">
    <span class="lbl">알림</span>
    <div class="sw" id="sw"><span class="knob"></span><span class="pulse" id="pulse"></span></div>
  </div>
  <button class="play" id="play" type="button" aria-label="play sound"><span class="tri"></span></button>
</div>
css
.wrap{position:relative;width:88%;height:82%;display:grid;place-items:center}
.row{display:flex;align-items:center;gap:12px;padding:14px 18px;border:1px solid var(--line);border-radius:14px;background:var(--surface)}
.lbl{font-size:13px;color:var(--fg)}
.sw{position:relative;width:44px;height:26px;border-radius:13px;background:var(--line);transition:background .18s}
.sw[data-on]{background:var(--accent-3)}
.knob{position:absolute;top:2px;left:2px;width:22px;height:22px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.3);transition:left .18s ease}
.sw[data-on] .knob{left:20px}
.pulse{position:absolute;inset:-6px;border-radius:16px;border:1.5px solid var(--accent-3);opacity:0}
.pulse.go{animation:pulse .5s ease-out}
@keyframes pulse{0%{opacity:.7;transform:scale(.9)}100%{opacity:0;transform:scale(1.3)}}
@media (min-width:460px){
  .row{gap:22px;padding:26px 34px;border-radius:20px}
  .lbl{font-size:22px}
  .sw{width:84px;height:48px;border-radius:24px}
  .knob{width:40px;height:40px;top:4px;left:4px}
  .sw[data-on] .knob{left:40px}
  .pulse{inset:-10px;border-radius:26px}
}
.play{position:absolute;right:0;bottom:0;width:clamp(28px,15%,40px);aspect-ratio:1;border-radius:50%;border:1px solid var(--line);background:var(--surface);display:grid;place-items:center;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.12)}
.play .tri{width:0;height:0;border-style:solid;border-width:6px 0 6px 9px;border-color:transparent transparent transparent var(--fg);margin-left:2px}
.play:active{transform:scale(.92)}
js
const sw = document.getElementById('sw');
const pulse = document.getElementById('pulse');
let on = false;
function flip() {
  on = !on;
  sw.toggleAttribute('data-on', on);
  pulse.classList.remove('go');
  void pulse.offsetWidth;
  pulse.classList.add('go');
}
setInterval(flip, 1700);
document.getElementById('play').addEventListener('click', () => {
  flip();
  const ctx = new (window.AudioContext || window.webkitAudioContext)();
  const size = Math.floor(ctx.sampleRate * 0.03);
  const buf = ctx.createBuffer(1, size, ctx.sampleRate);
  const d = buf.getChannelData(0);
  for (let i = 0; i < size; i++) d[i] = (Math.random() * 2 - 1) * (1 - i / size);
  const src = ctx.createBufferSource();
  src.buffer = buf;
  const filter = ctx.createBiquadFilter();
  filter.type = 'highpass';
  filter.frequency.value = 2200;
  const gain = ctx.createGain();
  gain.gain.value = 0.14;
  src.connect(filter).connect(gain).connect(ctx.destination);
  src.start();
  src.onended = () => ctx.close();
});

UI sound is narrower than an earcon — it's not a state change, but a stand-in for the tactile click your finger used to feel on a physical button. iOS's keyboard clicks, the camera shutter, and a toggle's little "clack" are classic examples, filling the tactile gap left by touchscreens.

Response speed is everything — it should play with near-zero perceived delay (ideally under 50ms) and stay quiet, around -20dB below peak, so it passes by unnoticed rather than announcing itself. For interactions that can fire many times a second (scrolling, dragging a slider), skip the sound entirely or keep it barely audible — repeated, it just becomes noise. Because silent-mode, low-vision, or deaf/hard-of-hearing users won't hear it, success always needs a visual confirmation too (color, size, position) — sound alone is never enough.

Used for keyboard clicks, toggle on/off, delete/confirm buttons, camera shutters, and unlock sounds across OS-level interactions.

When to use

Attach it to atomic, direct-touch actions like taps, toggles, and swipes. Skip it (or keep it minimal) for continuous gestures like drags and scrolls.