드롭다운 메뉴

Dropdown menu

버튼을 누르면 아래로 펼쳐지는 명령 목록. 하나를 고르면 즉시 실행되고 목록이 닫힙니다.

다른 이름: Select menuAction menuContext menuOverflow menu
···
html
<div class="wrap">
  <button class="trigger" id="mb" aria-haspopup="menu" aria-expanded="false">⋯</button>
  <ul class="menu" id="mn" role="menu">
    <li role="menuitem" tabindex="-1">이름 변경</li>
    <li role="menuitem" tabindex="-1">복제</li>
    <li role="menuitem" tabindex="-1" class="danger">삭제</li>
  </ul>
</div>
css
.wrap{position:relative;display:grid;place-items:center;width:100%;height:100%}
.trigger{width:38px;height:38px;border-radius:9px;border:1px solid var(--line);background:var(--surface);color:var(--fg);font-size:16px;cursor:pointer}
.menu{position:absolute;left:50%;bottom:calc(50% + 26px);transform:translate(-50%,6px);list-style:none;margin:0;
  width:140px;background:var(--surface);border:1px solid var(--line);border-radius:10px;padding:5px;
  box-shadow:0 14px 30px rgba(0,0,0,.2);opacity:0;pointer-events:none;transition:opacity .16s,transform .16s}
.menu[data-open]{opacity:1;pointer-events:auto;transform:translate(-50%,0)}
.menu li{padding:8px 10px;border-radius:6px;font-size:12px;color:var(--fg);cursor:pointer}
.menu li[data-hi]{background:var(--accent);color:#fff}
.menu li.danger{color:#e5484d}
.menu li.danger[data-hi]{background:#e5484d;color:#fff}
js
const mb = document.getElementById('mb'), mn = document.getElementById('mn');
const items = [...mn.querySelectorAll('li')];
function open(v) { mn.toggleAttribute('data-open', v); mb.setAttribute('aria-expanded', String(v)); if (!v) items.forEach(i => i.removeAttribute('data-hi')); }
let auto = true;
mb.addEventListener('click', () => { auto = false; open(mn.getAttribute('data-open') === null); });
document.addEventListener('click', (e) => { if (!mn.contains(e.target) && e.target !== mb) open(false); });
function loop() {
  if (!auto) return;
  open(true);
  let i = 0;
  const hi = setInterval(() => {
    if (!auto) return clearInterval(hi);
    items.forEach((it, idx) => it.toggleAttribute('data-hi', idx === i));
    i++;
    if (i > items.length) { clearInterval(hi); setTimeout(() => { if (auto) { open(false); setTimeout(loop, 900); } }, 300); }
  }, 380);
}
setTimeout(loop, 500);

메뉴 버튼에 aria-haspopup="menu"와 aria-expanded를, 목록에는 role="menu"와 각 항목에 role="menuitem"을 씁니다. 방향키(위/아래)로 항목 사이를 이동하고 Enter나 Space로 실행하며, 문자 키를 누르면 그 글자로 시작하는 항목으로 바로 건너뛰는 "타입어헤드"도 흔합니다.

콤보박스와 헷갈리기 쉽지만 목적이 다릅니다. 드롭다운 메뉴는 텍스트 입력이 전혀 없고 각 항목이 "복사", "삭제"처럼 즉시 실행되는 명령에 가깝습니다. 콤보박스는 입력창에 글자를 치면 후보가 걸러지는 폼 컨트롤로, 실행이 아니라 "값 하나를 선택"하는 게 목적입니다.

체크 가능한 메뉴 항목(예: "굵게" 토글)은 role="menuitemcheckbox"를 씁니다.