Menubar

메뉴바

A horizontal row of top-level items — File, Edit, View — each opening its own menu of commands below it.

Also known as: Application menu barMenu bar
···
html
<div class="mbw">
  <div class="mbinner">
    <div class="mbbar" role="menubar" aria-label="애플리케이션 메뉴" id="mbbar">
      <button role="menuitem" aria-haspopup="menu" aria-expanded="true" tabindex="0" id="mb1">파일</button>
      <button role="menuitem" aria-haspopup="menu" aria-expanded="false" tabindex="-1" id="mb2">편집</button>
      <button role="menuitem" aria-haspopup="menu" aria-expanded="false" tabindex="-1" id="mb3">보기</button>
    </div>
    <ul class="mbmenu" role="menu" aria-labelledby="mb1" id="mbmenu">
      <li role="menuitem" tabindex="-1">새 파일</li>
      <li role="menuitem" tabindex="-1">열기…</li>
      <li role="menuitem" tabindex="-1">저장</li>
    </ul>
  </div>
</div>
css
.mbw{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.mbinner{position:relative}
.mbbar{display:flex;background:var(--surface);border:1px solid var(--line);border-radius:9px 9px 0 0;overflow:hidden}
.mbbar button{border:0;background:none;color:var(--fg);font-size:11px;font-weight:600;padding:8px 14px;cursor:default}
.mbbar button[aria-expanded=true]{background:var(--accent);color:#fff}
.mbmenu{position:absolute;top:100%;left:0;list-style:none;margin:0;padding:5px;width:130px;background:var(--surface);border:1px solid var(--line);border-radius:0 8px 8px 8px;box-shadow:0 14px 30px rgba(0,0,0,.2)}
.mbmenu li{padding:7px 9px;border-radius:6px;font-size:11px;color:var(--fg)}
js
const items = [document.getElementById('mb1'), document.getElementById('mb2'), document.getElementById('mb3')];
const menu = document.getElementById('mbmenu');
const CONTENT = {
  mb1: ['새 파일', '열기…', '저장'],
  mb2: ['실행 취소', '다시 실행', '전체 선택'],
  mb3: ['확대', '축소', '전체 화면'],
};
function openIdx(i) {
  items.forEach((it, idx) => { it.setAttribute('aria-expanded', String(idx === i)); it.tabIndex = idx === i ? 0 : -1; });
  menu.setAttribute('aria-labelledby', items[i].id);
  menu.innerHTML = CONTENT[items[i].id].map((label) => '<li role="menuitem" tabindex="-1">' + label + '</li>').join('');
}
let auto = true, cur = 0;
openIdx(0);
items.forEach((it, i) => it.addEventListener('click', () => { auto = false; cur = i; openIdx(i); }));
document.getElementById('mbbar').addEventListener('keydown', (e) => {
  if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return;
  auto = false; e.preventDefault();
  cur = (cur + (e.key === 'ArrowRight' ? 1 : -1) + items.length) % items.length;
  openIdx(cur); items[cur].focus();
});
setInterval(() => { if (!auto) return; cur = (cur + 1) % items.length; openIdx(cur); }, 1400);

The container carries role="menubar", each top-level item is role="menuitem" with aria-haspopup="menu" and aria-expanded announcing its own submenu's state. Left/right arrows move between top-level items, and once one menu is already open, moving left or right conventionally opens the next item's menu automatically — no need to press it again. Down arrow moves into an open menu, and Esc closes it and returns focus to the menubar item.

The difference from a toolbar is what happens on press — a toolbar's buttons run immediately or toggle a state, while a menubar item never runs anything itself and always opens a submenu first. The difference from a dropdown menu is count — a dropdown menu pairs one trigger with one menu, while a menubar holds several triggers side by side inside one landmark, along with the rules for moving between them.

Rare in ordinary web apps, it resurfaces in products that reproduce a desktop application on the web — code editors, design tools.