액세스 가능한 드롭다운 탐색 만들기

27997 단어 a11ywebdevjavascript
서스펜션 네비게이션은 자바스크립트가 없는 상황에서 매우 간단하다. 이것은 내가 흔히 보는 실현 방식이다.HTML과 CSS는 매우 간단합니다.
HTML:
<nav>
  <ul class="menu">
    <li class="menu__item">
      <a href="/" class="menu__link">About</a>
      <ul class="submenu">
        <li class="submenu__item">
          <a class="submenu__link" href="/our-mission">Our Mission</a>
        </li>
        <li class="submenu__item">
          <a class="submenu__link" href="/our-team">Our Team</a>
        </li>
      </ul>
    </li>
  </ul>
</nav>
CSS:
.submenu {
  position: absolute;
  left: 0;
  padding: 0;
  list-style: none;
  height: 1px; 
  width: 1px;
  overflow: hidden;
  clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
  clip: rect(1px, 1px, 1px, 1px);
}

.menu__item:hover .submenu {
  padding: 0.5rem 0;
  width: 9rem;
  height: auto;
  background: #eedbff;
  clip: auto;
}
주의: visually-hidden 스타일이 아니라 display: none 스타일을 사용했습니다.이것은 접근성에 매우 중요합니다. 위의 링크에서 더 많은 내용을 읽을 수 있습니다.
나는 일반적인 스타일을 좀 뺐지만, 이 CSS는 정지 효과를 초래하는 원인이다.그러나, 아래gif에서 보듯이tab키를 사용하면 작업 방식이 달라집니다.

우리가 인코딩을 시작하기 전에, 나는 내가 이 문제를 해결하는 방법을 공유하고 싶다.우선, 내가 해결하고 싶은 문제는 정지할 때 내비게이션을 열 뿐만 아니라, 초점을 맞출 때 내비게이션을 열 수 있다는 것이다.둘째, 초점을 맞출 때 모든 하위 메뉴가 멈출 때처럼 열려 있는지 확인하고 싶습니다.셋째, 링크를 클릭하면 내가 떠날 때 특정한 하위 메뉴가 닫히는 것을 확보하고 싶습니다.이제 시작합시다!

초점에 스톱 효과 복사하기


우리는 :hover원소에 li위류가 있기 때문에 li원소에 주목해야 한다.하지만 내 블로그 글을 읽으면tabindexes의 개념을 알게 될 것이다.li 요소는tabindexes가 없지만 링크가 있습니다.개인적으로 좋아하는 것은 자바스크립트의 최고급 링크를 겨냥하고 초점 이벤트에 부모에게 클래스를 추가하는 것이다.우리 좀 더 알아보자.
const topLevelLinks = document.querySelectorAll('.menu__link');
console.log(topLevelLinks);
console.log 변수가 있을 때, 나는 맨 위 메뉴 항목의 노드 목록을 얻었다.내가 좋아하는 것은 forEach 이 대상들을 반복해서 훑어보고 parentElement 의 로그를 기록하는 것이다.
topLevelLinks.forEach(link => {
  console.log(link.parentElement);
});

지금 내가 해야 할 일은 링크에 focus 이벤트 탐지기를 추가하고 컨트롤러를 추가하는 것이다.this의 상하문이 정확한지 다시 확인하기 위해 기록this.
topLevelLinks.forEach(link => {
  link.addEventListener('focus', function() {
    console.log(this);
  });
});

나는 ES6+화살표 함수가 아니라 구식 함수를 사용한다. 왜냐하면 나는 this의 상하문이 목표라는 것을 확보하고 싶기 때문이다.만약 당신이 더 많은 것을 알고 싶다면, 이것에 관한 블로그 게시물이 매우 많다. (하하, 내가 거기서 무엇을 했는지 봐라.)어쨌든 지금 나는 그것을 원한다. 그러면 우리의 목표는 parentElement, 즉 li 이다.
topLevelLinks.forEach(link => {
  link.addEventListener('focus', function() {
    console.log(this.parentElement);
  });
});

이 부원소는 우리가 조준해야 할 것이다.내가 해야 할 일은 우리가 컨트롤러에 로그인한 리에 클래스를 추가하는 것이다.그리고 내가 할 일은 CSS 클래스를 사용하여 우리가 :hover 에 있는 스타일을 복제하는 것이다.
topLevelLinks.forEach(link => {
  link.addEventListener('focus', function() {
    this.parentElement.classList.add('focus');
  });
});

.menu__item:hover .submenu,
.menu__item.focus .submenu {
  padding: 0.5rem 0;
  width: 9rem;
  height: auto;
  background: #eedbff;
  clip: auto;
}

보시다시피 메뉴는 우리가 떠난 후에 닫히지 않았습니다. 이것은 제가 열거한 행동 항목 중의 하나입니다.그 전에 blur 사건과 이것이 무엇을 의미하는지 알아보자.

모호한 사건


모질라 docs에 따르면 요소가 초점을 잃을 때 촉발됩니다blur event.마지막 하위 메뉴 항목이 초점을 잃을 때까지 하위 메뉴를 열기를 원합니다.그래서 우리가 해야 할 일은 모호한 초점류를 삭제하는 것이다.
내가 좋아하는 첫 번째 일은 우리가 가지고 있는forEach 순환에서 존재하는지 확인하는 것이다nextElementSibling.
topLevelLinks.forEach(link => {
  link.addEventListener('focus', function() {
    this.parentElement.classList.add('focus');
  });

  console.log(link.nextElementSibling);
});

다음에 내가 해야 할 일은 조건을 만드는 것이다.하위 메뉴가 있다면, 우리는 아래 코드만 실행하고 싶습니다.다음은 내가 한 일이다.
topLevelLinks.forEach(link => {
  link.addEventListener('focus', function() {
    this.parentElement.classList.add('focus');
  });

  if (link.nextElementSibling) {
    const subMenu = link.nextElementSibling;
    console.log(subMenu);
    console.log(subMenu.querySelectorAll('a'));
  }
});

내가 subMenuquerySelectorAll를 기록한 이유는 시각 학습을 위해서이다.이 두 개의 하위 메뉴 요소가 모두 정확하게 위치를 정하고 그 안에 연결된 노드 목록을 보니 나는 매우 기쁘다.그래서 내가 여기서 하고 싶은 것은 그 중의 마지막 링크querySelectorAll를 겨냥한 것이다.우리는 그것을 변수에 넣어서 더욱 읽을 수 있게 합시다.
topLevelLinks.forEach(link => {
  link.addEventListener('focus', function() {
    this.parentElement.classList.add('focus');
  });

  if (link.nextElementSibling) {
    const subMenu = link.nextElementSibling;
    const subMenuLinks = subMenu.querySelectorAll('a');
    const lastLinkIndex = subMenuLinks.length - 1;
    console.log(lastLinkIndex);
    const lastLink = subMenuLinks[lastLinkIndex];
    console.log(lastLink);
  }
});

마지막 링크마다 클래스 li 를 삭제하는 모호한 이벤트를 추가하고 싶습니다.우선 우리가 예상한 결과를 얻었는지 확인하기 위해 link.parentElement 를 봅시다.
topLevelLinks.forEach(link => {
  link.addEventListener('focus', function() {
    this.parentElement.classList.add('focus');
  });

  if (link.nextElementSibling) {
    const subMenu = link.nextElementSibling;
    const subMenuLinks = subMenu.querySelectorAll('a');
    const lastLinkIndex = subMenuLinks.length - 1;
    const lastLink = subMenuLinks[lastLinkIndex];

    lastLink.addEventListener('blur', function() {
      console.log(link.parentElement);
    });
  }
});

이제 우리는 우리가 바라는 것을 얻었다. 나는 사건 탐지기에 초점을 맞추는 것과 상반된 일을 할 것이다.
topLevelLinks.forEach(link => {
  link.addEventListener('focus', function() {
    this.parentElement.classList.add('focus');
  });

  if (link.nextElementSibling) {
    const subMenu = link.nextElementSibling;
    const subMenuLinks = subMenu.querySelectorAll('a');
    const lastLinkIndex = subMenuLinks.length - 1;
    const lastLink = subMenuLinks[lastLinkIndex];

    lastLink.addEventListener('blur', function() {
      link.parentElement.classList.remove('focus');
    });
  }
});

내가 해야 할 마지막 일은 초점 사건 탐지기를 이 조건 문장에 놓는 것이다.사실상, 우리는 하위 메뉴가 없는 항목에 초점 클래스를 추가할 필요가 없다.
topLevelLinks.forEach(link => {
  if (link.nextElementSibling) {
    link.addEventListener('focus', function() {
      this.parentElement.classList.add('focus');
    });

    const subMenu = link.nextElementSibling;
    const subMenuLinks = subMenu.querySelectorAll('a');
    const lastLinkIndex = subMenuLinks.length - 1;
    const lastLink = subMenuLinks[lastLinkIndex];

    lastLink.addEventListener('blur', function() {
      link.parentElement.classList.remove('focus');
    });
  }
});

기타 과제


이 박문은 갈수록 길어지기 때문에 아마도 다음 주에 나는 후속 문장을 한 편 만들 것이다.내 후속 게시물 중 내가 아직 해결하지 못한 것이 하나 있다. 바로 메뉴에서 어떻게 후퇴하는가이다.tabshift 키를 동시에 사용하면 메뉴로 돌아갈 때 효과가 없습니다.만약 당신이 별도의 도전을 원한다면, 스스로 해 보세요!
지금 이대로!만약 이것이 나와 다르다면, 나는 네가 어떻게 해결 방안을 생각해 냈는지 매우 보고 싶다.너의 생각을 나에게 알려줘!

좋은 웹페이지 즐겨찾기