inert는 요소와 그 자손 전체를 "상호작용 불가" 상태로 만드는 HTML 불리언 속성이다. inert가 걸린 영역은 클릭이 먹지 않고, Tab 포커스가 들어가지 않으며, 스크린 리더의 접근성 트리에서도 빠진다. 화면 밖으로 밀어둔 사이드 패널, 뒤에 깔린 배경처럼 "지금은 없는 셈 쳐야 하는" UI를 다룰 때 쓴다.
접근성에서 가장 자주 새는 구멍이 바로 이거다. 눈으로는 안 보이는데 Tab을 누르면 포커스가 화면 밖 요소로 사라지는 현상. inert는 이 문제를 표준 한 방으로 막는다.
어떤 문제를 푸는가
모바일 내비게이션 드로어를 떠올려 보자. 닫힌 상태에서 transform: translateX(-100%)로 화면 밖에 밀어뒀다고 하자. 시각적으론 사라졌지만, 그 안의 링크들은 여전히 DOM에 살아 있어 포커스를 받는다. 키보드 사용자가 Tab을 누르면 포커스가 보이지 않는 메뉴로 빨려 들어가 "포커스가 실종되는" 경험을 한다. 스크린 리더 사용자도 마찬가지로 화면 밖 콘텐츠를 읽게 된다.
예전 해법은 처참했다. 모든 포커스 가능 요소에 tabindex="-1"을 걸고, aria-hidden을 바르고, 열리면 되돌리고… 관리 지옥이었다. inert는 이 전부를 대체한다.
사용법 — 속성 하나
<aside id="drawer" class="drawer" inert>
<a href="/a">메뉴 A</a>
<a href="/b">메뉴 B</a>
</aside>
<script>
const drawer = document.getElementById('drawer')
function open() {
drawer.inert = false // 상호작용 활성화
drawer.classList.add('open')
}
function close() {
drawer.inert = true // 다시 비활성화
drawer.classList.remove('open')
}
</script>
DOM 프로퍼티 element.inert = true/false로 토글하면 끝이다. 자손 전체에 한꺼번에 적용된다는 게 핵심이다. 개별 요소를 일일이 손댈 필요가 없다.
대표 활용처
- 커스텀 모달의 배경. 모달을 열 때
<main>에 inert를 걸면 배경 전체가 상호작용 불가가 된다. (참고로<dialog>.showModal()은 이걸 자동으로 해준다.) - 오프캔버스 메뉴·드로어. 닫혀 있을 때 inert.
- 로딩·전송 중 폼 잠금. 제출 중인 폼 전체를 잠깐 inert로 막아 중복 클릭을 방지.
- 캐러셀의 비활성 슬라이드. 보이지 않는 슬라이드의 링크가 포커스 잡히지 않도록.
혼동하기 쉬운 것들
| 방법 | 포커스 차단 | 스크린리더 숨김 | 시각적 숨김 |
|---|---|---|---|
| inert | 예 | 예 | 아니오 |
| display:none | 예 | 예 | 예 |
| aria-hidden | 아니오 | 예 | 아니오 |
| visibility:hidden | 예 | 예 | 예(자리 유지) |
핵심 차이가 보인다. inert는 시각적으로는 그대로 두면서 상호작용과 접근성만 죽인다. 슬라이드 애니메이션으로 부드럽게 나타나야 하는 드로어처럼, 화면엔 있지만 지금은 만질 수 없어야 하는 요소에 딱이다. display:none은 애니메이션이 불가능하고, aria-hidden은 포커스를 막지 못한다.
솔직히 예전에 aria-hidden만 발라두고 "접근성 처리 끝"이라 여긴 적이 있다. 나중에 키보드로 테스트해보니 포커스가 멀쩡히 숨긴 영역으로 들어가더라. aria-hidden은 스크린 리더에게만 숨길 뿐, 포커스는 못 막는다는 걸 그때 배웠다.
주의할 점
inert는 강력한 만큼 실수하면 통째로 못 쓰게 만든다. 열었는데 inert를 안 풀면 그 안이 전부 먹통이 된다. 또 중첩에 유의하자. 부모가 inert면 자식에서 inert=false로 되살릴 수 없다. inert는 위에서 아래로 무조건 전파된다. 미지원 구형 브라우저를 위해 공식 폴리필을 두면 안전하다.
자주 묻는 질문
모달을 만들 때 dialog를 쓰면 inert는 필요 없나요?
<dialog>.showModal()은 배경 inert를 자동 처리하므로 따로 안 걸어도 됩니다. 반면 직접 만든 커스텀 모달·오버레이라면 배경에 inert를 수동으로 걸어야 접근성이 완성됩니다.
inert와 disabled는 같은 건가요?
다릅니다. disabled는 폼 컨트롤 개별에만 쓰이고 값도 서버로 전송되지 않습니다. inert는 임의의 컨테이너와 그 자손 전체를 상호작용 불가로 만드는 더 넓은 개념입니다.
inert 영역도 마우스 선택(드래그)이 되나요?
텍스트 선택과 클릭 모두 차단됩니다. 링크 클릭, 버튼 클릭, 포커스, 선택 등 사용자 상호작용 전반이 막힌다고 보면 됩니다.
스타일로 흐리게 처리도 되나요?
inert 자체는 시각 효과가 없습니다. 필요하면 클래스를 함께 토글해 opacity나 pointer-events 스타일을 얹어 "비활성" 느낌을 주면 됩니다.

댓글 0