브라우저 히트 테스팅

Browser hit testing

겹친 요소 가운데 포인터 이벤트를 받을 대상을 결정합니다.

···
html
<div class="v"><header>HIT TEST <span id="label">top receives</span></header><div class="stage hit"><div class="back">back target</div><div class="front" id="front">top layer</div><div class="cursor">↖</div></div><div class="muted" id="result">target: top layer</div></div>
css
.v{width:min(94vw,760px);height:min(88vh,320px);padding:clamp(9px,2.4vmin,18px);border:1px solid var(--line);border-radius:12px;background:var(--surface);font:500 clamp(12px,2.4vmin,16px)/1.3 var(--font-sans,system-ui,sans-serif);display:flex;flex-direction:column;gap:clamp(5px,1.4vmin,10px);overflow:hidden}.v header{display:flex;align-items:center;justify-content:space-between;gap:8px;color:var(--accent);font-weight:700}.v header span{color:var(--muted);font-weight:500}.v .stage{flex:1;min-height:0;position:relative}.v .muted{color:var(--muted)}.v .active{background:color-mix(in srgb,var(--accent) 18%,var(--surface));border-color:var(--accent)!important;color:var(--fg)}.v button{font:inherit;color:var(--fg);background:var(--bg);border:1px solid var(--line);border-radius:7px;padding:5px 8px;cursor:pointer}.hit{display:grid;place-items:center}.back,.front{position:absolute;width:45%;height:52%;display:grid;place-items:center;border-radius:9px;border:2px solid var(--accent-2);background:color-mix(in srgb,var(--accent-2) 24%,var(--surface))}.back{left:23%;top:16%}.front{left:39%;top:31%;border-color:var(--accent);background:color-mix(in srgb,var(--accent) 28%,var(--surface));transition:opacity .3s}.front.pass{opacity:.45;border-style:dashed}.cursor{position:absolute;left:51%;top:48%;font-size:28px;color:var(--fg);filter:drop-shadow(1px 2px 1px var(--bg));animation:tap 1.8s ease-in-out infinite}@keyframes tap{50%{transform:scale(.8)}}
js
let pass=false;function tick(){pass=!pass;document.getElementById("front").classList.toggle("pass",pass);document.getElementById("label").textContent=pass?"top passes through":"top receives";document.getElementById("result").textContent="target: "+(pass?"back target":"top layer")}tick();setInterval(tick,1200)

히트 테스팅은 좌표에 있는 요소를 렌더 순서와 포인터 이벤트 설정에 따라 찾습니다. 위에 보이는 요소라도 `pointer-events: none`이면 아래 요소가 클릭을 받을 수 있습니다.

데모의 가짜 커서는 겹친 두 카드 위를 가리키고, 토글에 따라 실제 대상이 달라집니다. 보이는 레이어와 클릭 가능한 레이어가 다를 때 이 경로를 확인합니다.

언제 쓰나

오버레이나 드롭다운 뒤 버튼이 클릭되지 않는 문제를 디버깅할 때 씁니다.

페이지로 열기 ↗