액세스 우선 순위: 탭
27224 단어 a11ywebdevcssjavascript
이 글은 접근성과 자바스크립트에 관한 것으로 읽을 만하다. 자바스크립트가 필요한 것들은 접근성을 유지할 수 있다.
a11y와 JS - 비전통적인 낭만
린세 코파츠・ 2019년 1월 28일・ 6분 읽기
#a11y
#javascript
#frontend
#discuss
나는 재료 설계 규범을 느슨하게 따르는 옵션 카드식 내비게이션을 만들기로 결정했다. 우리의 완제품은 보기에 약간 이렇다
요구 사항
라벨에 접근할 수 있도록 키보드와 마우스를 사용하여 상호작용을 할 수 있어야 하며, 사용자가 보았다고 가정할 수도 없습니다.
키보드:
탭 키를 사용하여 탭
Return 키, 우리는 반드시 옵션 카드가 초점을 맞출 때 Return 키를 눌러
스페이스 바, 스페이스 바의 작용은 반환 키
Home 키, tablist
종료 키, 우리는 표 목록
화살표 키, 우리는 다음 탭이나 이전 탭으로 이동할 수 있어야 할 때, 오른쪽 단추나 왼쪽 단추를 누르지만, 초점이 우리의
tablist
에 있을 때만마우스:
탭을 클릭하여 활성
정지는 목표
무시력:
보너스
나는
<div>
을 가지고 있다. 이것은 전체 옵션 카드인 "element"를 포함하고 있으며, 이것은 ID를 필요로 한다. 이렇게 하면 우리는 뒤에 있는javascript에서 그것을 찾을 수 있고, tab-container
종류도 있다. 이렇게 하면 우리는 CSS로 그것을 스타일 설정할 수 있다.현재 우리는 일부 캐릭터가 생겼다. 캐릭터는 브라우저에서 모든 요소를 어떻게 처리해야 하는지 알려준다. 우리는
<ul>
이 있고 캐릭터는 tablist
이다.이것은 브라우저에 우리가 몇 개의 탭을 열거하고 있다는 것을 알려 줍니다. 이것은 화면 판독기가 탭을 볼 때 "두 개의 탭 중 하나를 선택하십시오."라고 말할 수 있다는 것을 의미합니다.다음은
<li>
, 역할은 tab
입니다. 이것은 우리가 전체'원소'를 제어하는 단추입니다. 우리는 각 탭에 tabindex
/0의 탭을 하나 주어야 하고 각 탭에는 aria-control
속성, 즉 대응하는 패널의 ID가 있어야 합니다.마지막으로true 또는false를 포함하는 aria-selected
이 있습니다. 이 옵션이 이벤트/선택 옵션인지에 따라 다릅니다.마지막으로
<main>
의 내용을 살펴보겠습니다. 우리는 각 패널에 <div>
을 제공합니다. 그들은 캐릭터 tabpanel
이 필요합니다. aria-expanded
의 속성이 필요합니다. 이 속성이 진짜인지 아닌지는 패널이 활동/전개 상태에 따라 달라집니다.ID 속성은 aria-control
요소에 해당하는 <li>
속성이 필요합니다.<div id="some_ID" class="tab-container">
<ul role="tablist">
<li role="tab" aria-controls="some_ID_1" tabindex="0" aria-selected="true">Tab 1</li>
<li role="tab" aria-controls="some_ID_2" tabindex="0" aria-selected="false">Tab 2</li>
</ul>
<main>
<div id="some_ID_1" role="tabpanel" aria-expanded="true">
<p>
content for 1
</p>
</div>
<div id="some_ID_2" role="tabpanel" aria-expanded="false">
<p>
content for 2
</p>
</div>
</main>
</div>
다음은 예시의 표식입니다.스타일
나는 이런 스타일들을 상세하게 소개하지 않을 것이다. 왜냐하면 그들은 개인적인 취향이기 때문이다. 그러나 나는 몇 가지 일을 지적할 것이다.
클래스
.tab-container
을 제외하고 나는 캐릭터를 선택기로 사용하려고 시도했다. 이것은 내가 선택기를 놓쳤다면 이것은 명백히 알 수 있지만 코드를 더욱 깨끗하게 할 수 있다는 것을 의미한다.나는 정지 효과가 하나 있지만 초점 효과가 아니다. 나는 네가
tabindex
으로 얻은 요강이 충분할 것이라고 생각한다. 만약 네가 동의하지 않는다면 언제든지 나에게 전화해라..tab-container {
overflow: hidden;
background: #fff;
}
.tab-container [role=tablist] {
display: flex;
margin: 0;
padding: 0;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
}
.tab-container [role=tab] {
position: relative;
list-style: none;
text-align: center;
cursor: pointer;
padding: 14px;
flex-grow: 1;
color: #444;
}
.tab-container [role=tab]:hover {
background: #eee;
}
.tab-container [role=tab][aria-selected=true] {
color: #000;
}
.tab-container [role=tab][aria-selected=true]::after {
content: "";
position: absolute;
width: 100%;
height: 4px;
background: #f44336;
left: 0;
bottom: 0;
}
.tab-container main {
padding: 0 1em;
position: relative;
}
.tab-container main [role=tabpanel] {
display: none;
}
.tab-container main [role=tabpanel][aria-expanded=true] {
display: block;
}
예시에 스타일을 추가합시다.JavaScript
다음으로, 나는 자바스크립트를 추가할 것이다.이것은 이 탭들이 더 이상 접근할 수 없다는 것을 의미합니다. 그렇습니까?물론 아니지, 어디 보자.
다시 한 번 말하지만, 나는 너무 많은 세부 사항을 말하지 않을 것이다. 왜냐하면 사실은 이것은 단지 사건 청중일 뿐이기 때문이다.너는 내가 왜 한 종류를 사용하는지 알고 싶을지도 모른다. 왜냐하면 나는 그것들을 좋아하기 때문이다. 너는 한 종류를 사용할 필요가 없다. 나는 단지 그것들을 사용하는 것을 좋아할 뿐이다.
나는 CSS와 같은 선택기 스타일을 사용하는데, 이것은 나에게 매우 의미가 있다.나는 단지 하나의 공공 함수만 있는데, 한 것은
aria-selected
과 aria-expanded
의 속성을 바꾸는 것이다.우리의 CSS는 모든 스타일 변경을 처리합니다.class TabController {
constructor(container) {
this.container = document.querySelector(container);
this.tablist = this.container.querySelector('[role=tablist]');
this.tabs = this.container.querySelectorAll('[role=tab]');
this.tabpanels = this.container.querySelectorAll('[role=tabpanel]');
this.activeTab = this.container.querySelector('[role=tab][aria-selected=true]');
this._addEventListeners();
}
// Private function to set event listeners
_addEventListeners() {
for (let tab of this.tabs) {
tab.addEventListener('click', e => {
e.preventDefault();
this.setActiveTab(tab.getAttribute('aria-controls'));
});
tab.addEventListener('keyup', e => {
if (e.keyCode == 13 || e.keyCode == 32) { // return or space
e.preventDefault();
this.setActiveTab(tab.getAttribute('aria-controls'));
}
})
}
this.tablist.addEventListener('keyup', e => {
switch (e.keyCode) {
case 35: // end key
e.preventDefault();
this.setActiveTab(this.tabs[this.tabs.length - 1].getAttribute('aria-controls'));
break;
case 36: // home key
e.preventDefault();
this.setActiveTab(this.tabs[0].getAttribute('aria-controls'));
break;
case 37: // left arrow
e.preventDefault();
let previous = [...this.tabs].indexOf(this.activeTab) - 1;
previous = previous >= 0 ? previous : this.tabs.length - 1;
this.setActiveTab(this.tabs[previous].getAttribute('aria-controls'));
break;
case 39: // right arrow
e.preventDefault();
let next = [...this.tabs].indexOf(this.activeTab) + 1;
next = next < this.tabs.length ? next : 0
this.setActiveTab(this.tabs[next].getAttribute('aria-controls'));
break;
}
})
}
// Public function to set the tab by id
// This can be called by the developer too.
setActiveTab(id) {
for (let tab of this.tabs) {
if (tab.getAttribute('aria-controls') == id) {
tab.setAttribute('aria-selected', "true");
tab.focus();
this.activeTab = tab;
} else {
tab.setAttribute('aria-selected', "false");
}
}
for (let tabpanel of this.tabpanels) {
if (tabpanel.getAttribute('id') == id) {
tabpanel.setAttribute('aria-expanded', "true");
} else {
tabpanel.setAttribute('aria-expanded', "false");
}
}
}
}
그리고 우리는 이렇게 실례화된 옵션 카드 내비게이션의 실례를 할 수 있다const someID = new TabController('#some_ID');
이 모든 것을 한데 결합시키다서명
나는 네가 이 작은 게시물을 좋아하고, 너의 어떤 사이트에서도 이 기술이나 전부를 마음대로 사용할 수 있기를 바란다.나는 정말 어떤 방법도 흥미롭게 들었다. 네가 이 점을 하려면 자바스크립트가 없을 것이다. 나는 이것이 방송팀을 통과할 수 있다고 생각하지만, 나는 지금 시도하지 않을 것이다.
읽어주셔서 감사합니다!
🦄❤🦄🦄🧠❤🦄
Reference
이 문제에 관하여(액세스 우선 순위: 탭), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/link2twenty/accessibility-first-tabs-ken텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)