HTML 드롭다운 메뉴

양식 드롭다운과 탐색 드롭다운은 마크업이 다른 서로 다른 구성 요소입니다. 메뉴가 전화기에서 작동하지 않는 일반적인 이유는 잘못된 메뉴를 선택하는 것입니다.

영문 원문 보기

HTML 드롭다운 메뉴는 두 가지 구성 요소 중 하나이며 두 가지 모두를 의미하는 단어입니다. 독자가 값을 선택하는 경우 <select>가 필요합니다. 독자가 어딘가로 가고 있다면 링크 목록을 표시하는 버튼이 필요합니다.

메뉴를 잘못 선택하면 노트북에서는 제대로 보이고 휴대폰에서는 사용할 수 없는 메뉴가 자주 발생합니다.

운영 체제에서 그린 옵션 목록과 함께 확장된 기본 선택 컨트롤입니다.
운영 체제에서 그린 옵션 목록과 함께 확장된 기본 선택 컨트롤입니다.

HTML 드롭다운 메뉴라고 불리는 두 가지

당신은 독자가 원하는 구성 요소 목록의 스타일링
제출할 값 하나를 선택하세요. <select> 시스템에 의해 제어됨
두 개, 세 개 중 하나를 선택하세요. 라디오 버튼 완전히 당신의 것
다른 페이지로 이동 버튼과 링크 목록 완전히 당신의 것
명령 실행 버튼과 버튼 목록 완전히 당신의 것
표시되는 내용 필터링 <select> 플러스 청취자 시스템에 의해 제어됨

세 번째와 네 번째 행은 사람들이 메뉴라고 부르는 행입니다. 첫 번째와 마지막은 대부분의 튜토리얼에서 보여주는 것이므로 이 문구를 검색하면 관련 없는 두 가지 답변이 반환됩니다.

양식 드롭다운

<label for="plan">Plan</label>
<select id="plan" name="plan">
  <option value="">Choose one</option>
  <option value="team">Team</option>
  <option value="org" selected>Organisation</option>
</select>

이것이 무료로 제공하는 세 가지 기능은 화살표 키를 사용한 키보드 탐색, 독자가 옵션 이름 입력을 시작할 때 자동 입력, 휴대폰의 기본 선택기입니다.

제공되지 않는 세 가지: 스타일이 지정된 옵션, 목록의 아이콘, 여러 열. 옵션 목록은 운영 체제에 의해 렌더링됩니다. CSS가 내부에 도달하지 않습니다.

디자인에 이러한 기능이 필요한 경우 선택을 사용하는 것이 아니라 메뉴를 만드는 것입니다. div를 스타일처럼 보이도록 스타일링하는 대신 추가 작업을 수락하세요.

긴 목록을 그룹화하는 것은 가치가 있습니다.

<optgroup label="Europe">
  <option value="de">Germany</option>
  <option value="fr">France</option>
</optgroup>

선택한 옵션 시작 설정에는 기본 선택 옵션에서 다루는 자체 규칙이 있습니다.

탐색 드롭다운

<div class="menu">
  <button type="button" aria-expanded="false" aria-controls="m1">Products</button>
  <ul id="m1" hidden>
    <li><a href="/reports">Reports</a></li>
    <li><a href="/dashboards">Dashboards</a></li>
    <li><a href="/invoices">Invoices</a></li>
  </ul>
</div>
.menu { position: relative; }
.menu ul { position: absolute; top: 100%; left: 0; margin: 0; padding: .25rem;
           list-style: none; background: #16181d; border: 1px solid #2c2f36; min-width: 12rem; }
var b = document.querySelector('.menu button');
var m = document.getElementById('m1');
b.addEventListener('click', function () {
  var open = b.getAttribute('aria-expanded') === 'true';
  b.setAttribute('aria-expanded', String(!open));
  m.hidden = open;
});
document.addEventListener('keydown', function (e) {
  if (e.key === 'Escape' && !m.hidden) { m.hidden = true; b.setAttribute('aria-expanded', 'false'); b.focus(); }
});
트리거 버튼 아래에 세 개의 링크가 표시된 탐색 드롭다운이 열립니다.
트리거 버튼 아래에 세 개의 링크가 표시된 탐색 드롭다운이 열립니다.

호버 메뉴가 실패하는 이유

클래식 CSS 메뉴에는 :hover의 목록이 표시됩니다. 스크립트가 필요하지 않으며 CSS를 사용해도 해결되지 않는 두 가지 문제가 있습니다.

휴대폰과 태블릿에는 호버 상태가 없습니다. 일부 브라우저에서는 탭이 마우스 오버로 합성되므로 다른 브라우저에서는 메뉴가 처음 탭할 때 열리기도 하고 다른 때는 열리지 않습니다.

키보드 사용자는 전혀 호버링하지 않습니다. :focus-within를 추가하면 도움이 되지만 초점을 다른 곳으로 이동하지 않으면 메뉴를 닫을 수 없습니다.

클릭 트리거는 하나의 코드 경로로 포인터, 터치 및 키보드를 처리합니다. 그것이 여덟 줄을 쓰는 이유이다.

사용 중에만 나타나는 세 번째 문제가 있습니다. 포인터가 다른 곳으로 이동하는 동안 포인터를 교차하면 호버 메뉴가 열리므로 독자는 읽고 있는 내용을 포함하도록 요청하지 않은 패널을 얻게 됩니다.

지연은 일반적인 패치입니다. 그들은 메뉴를 원했던 사람들에게 메뉴가 부진하다고 느끼게 만들어 불만을 다른 불만으로 바꾸게 됩니다.

메뉴가 지켜야 할 네 가지 규칙

  1. 트리거는 <button>입니다. div는 포커스를 받을 수 없으며 아무 것도 발표되지 않습니다. href="#" 링크가 페이지로 이동합니다.
  2. aria-expanded는 현실과 일치합니다. 열릴 때뿐만 아니라 모든 상태 변경에 대해 설정합니다.
  3. Escape는 항목을 닫고 초점은 트리거로 돌아갑니다. 그렇지 않으면 키보드 사용자는 마지막 항목 이후에 발이 묶입니다.
  4. 바깥쪽을 클릭하면 닫힙니다. document를 바인딩하고 클릭이 메뉴 내부에 도달했는지 확인합니다.

라벨 지정 컨트롤은 트리거가 눈에 보이는 텍스트가 없는 아이콘인 경우 수행할 작업을 다룹니다.

메뉴 내부의 화살표 키 탐색

선택하면 화살표 키가 제공됩니다. 버튼과 목록 메뉴가 이를 구현해야 하며, 약 10줄 정도입니다.

var items = m.querySelectorAll('a');
m.addEventListener('keydown', function (e) {
  var i = Array.prototype.indexOf.call(items, document.activeElement);
  if (e.key === 'ArrowDown') { e.preventDefault(); items[(i + 1) % items.length].focus(); }
  if (e.key === 'ArrowUp')   { e.preventDefault(); items[(i - 1 + items.length) % items.length].focus(); }
  if (e.key === 'Home')      { e.preventDefault(); items[0].focus(); }
  if (e.key === 'End')       { e.preventDefault(); items[items.length - 1].focus(); }
});

preventDefault 호출은 독자가 목록을 이동하는 동안 페이지 스크롤을 중지합니다. 이는 그렇지 않으면 작동하는 메뉴가 잘못된 것처럼 느끼게 만드는 부분입니다.

키보드로 메뉴를 열면 첫 번째 항목에 초점을 맞추고 클릭으로 열면 트리거에 초점을 둡니다. 그 차이는 작으며, 이것이 원주민처럼 느껴지는 메뉴와 그렇지 않은 메뉴를 구분하는 것입니다.

탐색하는 선택

피할 수 있도록 명명할 가치가 있는 패턴: 변경 이벤트가 독자를 다른 페이지로 보내는 <select>입니다.

옵션을 화살표로 이동하면 독자가 원하는 항목에 도달하기 전에 모든 단계에서 벗어나기 때문에 컴팩트하고 키보드 사용이 중단됩니다. 반드시 사용해야 한다면 변경보다는 별도의 Go 버튼을 사용하세요.

라이브러리 없이 포지셔닝

목록의 position: absolute 및 래퍼의 position: relative는 목록을 버튼 아래에 배치합니다. 두 가지 조정으로 가장자리를 처리합니다.

오른쪽 가장자리 근처에 있는 메뉴의 경우 left: 0를 right: 0로 교체하여 안쪽으로 열리도록 합니다. 스크롤 컨테이너 내부 메뉴의 경우 절대 목록은 조상의 overflow: hidden에 의해 잘리므로 조상에는 overflow: visible가 필요합니다.

Flexbox는 막대 자체를 따라 트리거 행을 처리하고 막대 구축은 해당 레이아웃의 나머지 부분을 다룹니다.

확인 중

메뉴는 키보드로 열리며 첫 번째 항목에 포커스가 표시됩니다.
메뉴는 키보드로 열리며 첫 번째 항목에 포커스가 표시됩니다.

HTML 파일 오프너에서 페이지를 열고 마우스를 터치하지 않고 사용하세요. Tab 키를 눌러 트리거로 이동하고 Enter 키를 누른 다음 항목을 화살표로 가리키고 Esc 키를 누르세요.

그런 다음 창을 전화기 너비로 좁히고 탭만으로 작업을 수행합니다. 그 두 패스는 거의 모든 것을 포착합니다.

작동하면 HTML을 NOS 문서에 붙여넣습니다. 메뉴는 문서 자체 주소에서 렌더링되고 실행되므로 열리지 않는 파일 대신 휴대폰에서 열리는 링크를 보냅니다.

자주 묻는 질문

드롭다운 메뉴의 HTML 태그는 무엇입니까?

양식 컨트롤의 경우 내부에 옵션 요소가 포함된 선택입니다. 탐색 메뉴에는 단일 태그가 없습니다. 버튼과 목록으로 구성하고 버튼이 활성화되면 목록을 표시합니다.

내 호버 드롭다운이 전화기에서 작동하지 않는 이유는 무엇입니까?

전화기에는 호버 상태가 없습니다. 첫 번째 탭은 마우스 오버로 처리되어 종종 메뉴를 열고, 두 번째 탭은 링크를 따르지만 동작이 다양하고 일부 메뉴에 접근할 수 없게 됩니다. 대신 클릭 또는 포커스 트리거를 사용하세요.

선택 항목 내에서 옵션의 스타일을 지정할 수 있나요?

아주 약간이며 운영 체제에 따라 다릅니다. 옵션 목록은 CSS가 아닌 시스템에 의해 그려집니다. 디자인에 스타일 옵션이 필요한 경우 선택보다는 버튼과 목록 메뉴가 필요합니다.

드롭다운 메뉴 키보드에 액세스하려면 어떻게 해야 합니까?

실제 버튼을 트리거로 사용하고, 상태를 반영하도록 aria-expanded를 설정하고, 링크 목록에 항목을 넣고, Escape 메뉴를 닫고, 닫히면 버튼으로 포커스를 되돌립니다. 선택은 브라우저에서 이 모든 것을 가져옵니다.