Đến nội dung chính

Menu nổi

Nơi chứa các hành động phụ của một dòng, khi nhiều quá không thể bày hết thành nút.

Lớp phủ

Xem trước trực tiếp

Nguồn

<div class="dc-mo">
  <details class="dc-mo__root" open>
    <summary class="dc-mo__trigger"><svg viewBox="0 0 16 16" aria-hidden="true" focusable="false"><circle cx="8" cy="3" r="1.4" /><circle cx="8" cy="8" r="1.4" /><circle cx="8" cy="13" r="1.4" /></svg><span class="dc-sr">주문 20260907-118 메뉴 열기</span></summary>
    <div class="dc-mo__pop" role="menu" aria-label="주문 메뉴">
      <button class="dc-mo__item" type="button" role="menuitem"><span class="dc-mo__label">이름 바꾸기</span><kbd class="dc-mo__key">F2</kbd></button>
      <button class="dc-mo__item" type="button" role="menuitem"><span class="dc-mo__label">복제하기</span><kbd class="dc-mo__key">Ctrl D</kbd></button>
      <hr class="dc-mo__sep">
      <div role="group" aria-labelledby="dc-mo-send">
        <p class="dc-mo__head" id="dc-mo-send">보내기</p>
        <button class="dc-mo__item" type="button" role="menuitem"><span class="dc-mo__label">링크 복사</span></button>
        <button class="dc-mo__item" type="button" role="menuitem"><span class="dc-mo__label">엑셀로 내려받기</span></button>
      </div>
      <hr class="dc-mo__sep">
      <button class="dc-mo__item dc-mo__item--danger" type="button" role="menuitem"><span class="dc-mo__label">주문 지우기</span><kbd class="dc-mo__key">Del</kbd></button>
    </div>
  </details>
</div>
.dc-mo { display: flex; align-items: flex-start; justify-content: flex-end; min-height: 340px; font-family: var(--dc-font); }
.dc-mo--up { align-items: flex-end; }
.dc-mo__root { position: relative; }
.dc-mo__trigger {
  display: grid; place-items: center; width: 40px; height: 40px;
  border: 1px solid var(--dc-line-field); border-radius: var(--dc-r-sm);
  background: var(--dc-surface); color: var(--dc-text);
  list-style: none; cursor: pointer;
  transition: background var(--dc-fast);
}
.dc-mo__trigger::-webkit-details-marker { display: none; }
.dc-mo__trigger:hover { background: var(--dc-sunken); }
.dc-mo__trigger svg { width: 16px; height: 16px; fill: currentColor; }
.dc-mo__pop {
  position: absolute; top: calc(100% + var(--dc-1)); right: 0; z-index: 5;
  min-width: 240px; padding: var(--dc-2);
  background: var(--dc-surface);
  border: 1px solid var(--dc-line); border-radius: var(--dc-r-md);
  box-shadow: var(--dc-sh-2);
}
.dc-mo__pop--up { top: auto; bottom: calc(100% + var(--dc-1)); }
.dc-mo__head {
  margin: 0; padding: var(--dc-2) var(--dc-2) var(--dc-1);
  font-size: 12px; font-weight: 700; color: var(--dc-text-mute);
}
.dc-mo__item {
  display: flex; align-items: center; gap: var(--dc-3);
  width: 100%; min-height: 40px; padding: 0 var(--dc-2);
  border: 0; border-radius: var(--dc-r-xs);
  background: transparent; color: var(--dc-text);
  font-family: inherit; font-size: 14px; text-align: left;
  transition: background var(--dc-fast);
}
.dc-mo__item:hover { background: var(--dc-sunken); }
.dc-mo__item--danger { color: var(--dc-danger); }
.dc-mo__item--danger:hover { background: var(--dc-danger-soft); }
.dc-mo__label { flex: 1 1 auto; }
.dc-mo__key {
  flex: none; padding: 1px var(--dc-1);
  border: 1px solid var(--dc-line); border-radius: var(--dc-r-xs);
  background: var(--dc-sunken); color: var(--dc-text-sub);
  font-family: var(--dc-mono); font-size: 11px;
}
.dc-mo__sep { height: 1px; margin: var(--dc-2) 0; border: 0; background: var(--dc-line); }
.dc-mo__sub { position: relative; }
.dc-mo__subtrigger {
  display: flex; align-items: center; gap: var(--dc-3);
  min-height: 40px; padding: 0 var(--dc-2);
  border-radius: var(--dc-r-xs); color: var(--dc-text);
  font-size: 14px; list-style: none; cursor: pointer;
  transition: background var(--dc-fast);
}
.dc-mo__subtrigger::-webkit-details-marker { display: none; }
.dc-mo__subtrigger:hover { background: var(--dc-sunken); }
.dc-mo__caret { flex: none; color: var(--dc-text-mute); font-size: 11px; }
.dc-mo__subpop {
  position: absolute; top: calc(-1 * var(--dc-2)); right: calc(100% + var(--dc-2));
  z-index: 6; min-width: 200px; padding: var(--dc-2);
  background: var(--dc-surface);
  border: 1px solid var(--dc-line); border-radius: var(--dc-r-md);
  box-shadow: var(--dc-sh-2);
}
@media (max-width: 420px) {
  .dc-mo__pop { min-width: 0; width: calc(100vw - var(--dc-7)); }
  .dc-mo__subpop { position: static; right: auto; min-width: 0; margin-top: var(--dc-1); box-shadow: none; }
}

Cách dùng

  • Để một hai hành động dùng hằng ngày ở ngoài, phần còn lại đưa vào menu
  • Tách các mục phá huỷ xuống cuối bằng một đường kẻ
  • Khi dưới nút không còn chỗ, hãy lật menu mở lên trên
  • Nếu nút chỉ có biểu tượng, tên trong dc-sr phải nói đây là menu của cái gì

Điểm cần lưu ý

  • Phím mũi tên phải di chuyển được giữa các mục — đừng để Tab là cách duy nhất
  • Chỉ nên có một cấp menu con, và trên màn hình cảm ứng thì mở bung tại chỗ dễ đọc hơn

Tiếp theo