inert Attribute

inert 속성

An HTML attribute that removes an element and all its descendants from focus, click, and screen readers at once — for locking the background behind a modal.

Also known as: inert
···
html
<div class="wrap">
  <div class="badge" id="badge"><svg viewBox="0 0 10 10"><path id="bpath" d="M1.5 5.2l2.6 2.6L8.5 2.4" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg><span id="btext">확인 중</span></div>
  <div class="bg" id="bg">
    <button class="bgbtn">배경 버튼 A</button>
    <button class="bgbtn">배경 버튼 B</button>
  </div>
  <div class="modal" id="modal">모달 열림 — 배경 비활성</div>
</div>
css
.wrap{position:relative;width:min(260px,92%);height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}
.bg{display:grid;gap:8px;transition:opacity .3s}
.bg[inert],.bg.fallback-inert{opacity:.35}
.bgbtn{padding:8px 14px;border-radius:8px;border:1px solid var(--line);background:var(--surface);color:var(--fg);font-size:11px}
.modal{padding:8px 12px;border-radius:8px;background:var(--accent);color:#fff;font-size:10px;font-weight:700;
  opacity:0;visibility:hidden;transition:opacity .3s}
.modal.show{opacity:1;visibility:visible}
.badge{position:absolute;top:10px;right:10px;display:flex;align-items:center;gap:5px;padding:4px 9px;border-radius:999px;font-size:10px;font-weight:700;background:var(--bg);border:1px solid var(--line);color:var(--accent-3);z-index:2}
.badge.no{color:var(--accent-2)}
.badge svg{width:9px;height:9px}
js
const ok = 'inert' in HTMLElement.prototype;
const b=document.getElementById('badge'),p=document.getElementById('bpath'),t=document.getElementById('btext');
b.classList.toggle('no', !ok);
p.setAttribute('d', ok ? 'M1.5 5.2l2.6 2.6L8.5 2.4' : 'M2 2l6 6M8 2l-6 6');
t.textContent = ok ? 'inert 지원됨' : '미지원 · tabindex 폴백';
const bg = document.getElementById('bg'), modal = document.getElementById('modal'), buttons = [...bg.querySelectorAll('.bgbtn')];
function lock(on){
  if (ok) { on ? bg.setAttribute('inert','') : bg.removeAttribute('inert'); }
  else {
    bg.classList.toggle('fallback-inert', on);
    buttons.forEach((btn) => { on ? btn.setAttribute('tabindex','-1') : btn.removeAttribute('tabindex'); btn.style.pointerEvents = on ? 'none' : ''; });
  }
  modal.classList.toggle('show', on);
}
let on = false;
setInterval(() => { on = !on; lock(on); }, 1800);

A common accessibility bug: a modal is open, but pressing Tab lets focus leak into the background content. Preventing it meant giving every background button, link, and input `tabindex="-1"`, adding `aria-hidden="true"`, and setting `pointer-events:none` in CSS — and re-doing it whenever a new focusable element was added to the background.

A single `inert` attribute on the parent removes the whole subtree from focus, click, text selection, and screen-reader access. Instead of tracking every descendant, it declares "make this entire region dead." `<dialog>.showModal()` handles its background this way internally.

Check caniuse/MDN baseline for support. Without it, manually toggling `tabindex="-1"`/`aria-hidden` on every focusable background element and setting `pointer-events:none` in CSS is still required.

When to use

Fully excluding background content from focus and click while a modal is open.