ARIA 접근성 가이드

속성 · 관계 · 전역

aria-controls

이 요소가 내용이나 표시 여부를 제어하는 다른 요소를 ID로 연결합니다.

기초

한눈에 보기

구분
속성 (Property)
분류
관계
값 형식
ID 참조 목록 (ID reference list) — 공백으로 구분
기본값
없음
적용 범위
모든 요소 (전역 속성)
HTML 대체
없음 (<output for>, <label for>는 다른 관계를 나타냅니다)

설명

aria-controls는 "이 버튼(또는 탭, 입력 상자)을 조작하면 저 요소의 내용이나 표시 여부가 바뀝니다"라는 관계를 ID로 알립니다. 예를 들어 tab은 자신이 보여 주는 tabpanel을, 펼침 버튼은 펼쳐지는 패널을, combobox는 팝업 목록 상자를, 캐러셀의 이전·다음 버튼은 슬라이드 영역을 가리킵니다. 여러 요소를 제어하면 ID를 공백으로 구분해 나열합니다.

명세상 전역 속성이므로 어느 요소에나 쓸 수 있고, scrollbar에서는 필수 속성입니다(스크롤바가 어느 영역을 스크롤하는지 알려야 함). APG의 탭·콤보박스·캐러셀 패턴도 이 속성 사용을 안내합니다.

다만 보조기술 지원은 제한적입니다. JAWS는 "JAWS 키+Alt+M으로 제어되는 요소로 이동" 같은 안내와 이동 기능을 제공하지만, NVDA·VoiceOver·TalkBack은 이 관계를 거의 안내하지 않습니다. 그래서 aria-controls만으로 관계를 전달할 수 있다고 기대하면 안 되며, 펼침 상태는 aria-expanded, 선택 상태는 aria-selected로 함께 알리고, 제어 대상은 DOM 순서상 바로 뒤에 두는 것이 더 확실한 방법입니다.

그럼에도 이 속성은 넣어 둘 가치가 있습니다. 브라우저는 관계를 접근성 API로 노출하므로 이를 활용하는 보조기술 사용자는 이동이 빨라지고, 코드를 읽는 개발자·테스터에게도 어떤 요소가 무엇을 제어하는지 분명해집니다. 단, 가리키는 ID는 반드시 존재해야 합니다. 접힌 패널을 DOM에서 아예 제거하는 구현이라면 패널이 없는 동안에는 속성도 빼는 것이 원칙입니다.

검수할 때는 값의 ID가 문서 안에 실제로 있는지(오타·중복 ID 확인), 가리키는 요소가 정말 이 요소로 제어되는지, 그리고 이 속성 하나에만 의존하지 않고 aria-expanded나 DOM 순서로도 관계가 전달되는지 확인합니다.

값

값
값의미
<ID 목록>이 요소가 제어하는 요소들의 ID입니다. 여러 개면 공백으로 구분합니다. (예: panel-1, grid-1 chart-1)

사용 예

펼침 버튼과 패널

권장HTML
<button type="button" aria-expanded="false" aria-controls="faq-1">
  배송은 얼마나 걸리나요?
</button>
<div id="faq-1" hidden>주문 후 2~3일 안에 도착합니다.</div>

펼침 상태는 aria-expanded로 알리고, 패널은 버튼 바로 뒤에 둡니다.

탭과 탭 패널

권장HTML
<div role="tablist" aria-label="상품 정보">
  <button role="tab" id="tab-1" aria-selected="true" aria-controls="panel-1">상세 설명</button>
  <button role="tab" id="tab-2" aria-selected="false" aria-controls="panel-2" tabindex="-1">리뷰</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">...</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>...</div>

여러 요소를 동시에 제어하는 필터

HTML
<fieldset>
  <legend>표시할 지역</legend>
  <label><input type="checkbox" aria-controls="sales-table sales-chart" checked> 서울</label>
  <label><input type="checkbox" aria-controls="sales-table sales-chart"> 부산</label>
</fieldset>
<table id="sales-table">...</table>
<figure id="sales-chart">...</figure>

존재하지 않는 ID를 가리킴

비권장HTML
<!-- 비권장: 패널이 DOM에 아직 없는데 ID를 가리킴, 펼침 상태 정보도 없음 -->
<button type="button" aria-controls="menu-panel">메뉴</button>

직접 해 보기

이전·다음 버튼이 aria-controls로 슬라이드 영역을 가리키는 캐러셀입니다. 버튼으로 슬라이드를 바꿔 보세요. 버튼의 aria-controls 값은 그대로이고, 제어 대상의 내용이 바뀝니다.

10월 25일 새벽 2시~4시 서버 점검이 있습니다.

화면낭독기에서는

화면낭독기 안내 예시 (표현은 화면낭독기·브라우저·버전에 따라 조금씩 다릅니다)
상황들리는 안내 (예)
펼침 버튼에 포커스 (NVDA)배송은 얼마나 걸리나요?, 버튼, 축소됨 (aria-controls 관계는 읽지 않음)
같은 버튼에 포커스 (JAWS)배송은 얼마나 걸리나요?, 버튼, 축소됨, 제어되는 요소로 이동하려면 JAWS 키+Alt+M을 누르세요 · JAWS
캐러셀 다음 공지 버튼을 누름신규 회원 가입 시 3,000원 쿠폰을 드립니다. (슬라이드 영역의 aria-live로 안내)

사용 지침

이렇게 쓰세요

  • 탭→탭 패널, 펼침 버튼→패널, 콤보박스→팝업처럼 실제 제어 관계에만 씁니다.
  • aria-expanded·aria-selected 등 상태 속성과 함께 써서 관계 이외의 정보도 전달합니다.
  • 제어 대상을 DOM 순서상 제어 요소 가까이(바로 뒤) 배치합니다.
  • scrollbar 역할에는 반드시 넣습니다(필수 속성).

이렇게 쓰지 마세요

  • aria-controls만 넣고 화면낭독기가 관계를 알려 줄 것이라고 기대하지 않습니다. 지원은 제한적입니다.
  • DOM에 없는 요소의 ID를 가리키지 않습니다. 대상을 제거하면 속성도 함께 제거합니다.
  • 단순히 다른 페이지 위치로 이동하는 링크나, 설명을 연결하는 용도로 쓰지 않습니다. 설명은 aria-describedby를 씁니다.

사용할 수 있는 역할

전역 속성이므로 모든 역할과 HTML 요소에 쓸 수 있습니다. 특히 다음 역할과 자주 함께 씁니다.

이 속성을 쓰는 패턴

참고 자료