액세스 우선 순위: 탭

나는 이 시리즈를 다른 원소로 하기로 결정했다.나의 영감은
이 글은 접근성과 자바스크립트에 관한 것으로 읽을 만하다. 자바스크립트가 필요한 것들은 접근성을 유지할 수 있다.


나는 재료 설계 규범을 느슨하게 따르는 옵션 카드식 내비게이션을 만들기로 결정했다. 우리의 완제품은 보기에 약간 이렇다

요구 사항


라벨에 접근할 수 있도록 키보드와 마우스를 사용하여 상호작용을 할 수 있어야 하며, 사용자가 보았다고 가정할 수도 없습니다.

키보드:


  • 탭 키를 사용하여 탭
  • 을 따라 포커스를 이동할 수 있어야 합니다.

  • Return 키, 우리는 반드시 옵션 카드가 초점을 맞출 때 Return 키를 눌러
  • 으로 이동할 수 있어야 한다

  • 스페이스 바, 스페이스 바의 작용은 반환 키
  • 과 유사해야 한다

  • Home 키, tablist
  • 의 첫 번째 옵션 카드를 선택해야 합니다

  • 종료 키, 우리는 표 목록
  • 에서 마지막 옵션 카드를 선택해야 합니다

  • 화살표 키, 우리는 다음 탭이나 이전 탭으로 이동할 수 있어야 할 때, 오른쪽 단추나 왼쪽 단추를 누르지만, 초점이 우리의 tablist에 있을 때만
  • 이 키보드는 here에서 찾을 수 있어야 한다

    마우스:


  • 탭을 클릭하여 활성
  • 으로 설정해야 합니다.

  • 정지는 목표
  • 의 지시를 제시해야 한다

    무시력:

  • 키보드 지원 의존
  • 은 화면 판독기를 사용해야 합니다.
  • 나는 이것이 우리가 필요로 하는 것이라고 믿는다. 비록 내가 틀렸다면, 나에게 말해 주십시오. 나도 위의 예가 우리의 명세서상의 모든 항목에 부합된다고 믿습니다.계속합시다.

    보너스


    나는 <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-selectedaria-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');
    
    이 모든 것을 한데 결합시키다

    서명


    나는 네가 이 작은 게시물을 좋아하고, 너의 어떤 사이트에서도 이 기술이나 전부를 마음대로 사용할 수 있기를 바란다.나는 정말 어떤 방법도 흥미롭게 들었다. 네가 이 점을 하려면 자바스크립트가 없을 것이다. 나는 이것이 방송팀을 통과할 수 있다고 생각하지만, 나는 지금 시도하지 않을 것이다.
    읽어주셔서 감사합니다!
    🦄❤🦄🦄🧠❤🦄

    좋은 웹페이지 즐겨찾기