Skip to content

Dropdown menu

For hiding several actions or options behind one button until someone asks for them.

Navigation

Live preview

Source

<div class="dc-dd">
  <details class="dc-dd__root" open>
    <summary class="dc-dd__trigger">
      <span class="dc-dd__label">정렬: 최신순</span>
      <span class="dc-dd__caret" aria-hidden="true">▾</span>
    </summary>
    <div class="dc-dd__pop">
      <p class="dc-dd__head">정렬 기준</p>
      <ul class="dc-dd__list">
        <li><a class="dc-dd__item" href="#" aria-current="true"><span class="dc-dd__check" aria-hidden="true">✓</span>최신순</a></li>
        <li><a class="dc-dd__item" href="#"><span class="dc-dd__check" aria-hidden="true"></span>인기순</a></li>
        <li><a class="dc-dd__item" href="#"><span class="dc-dd__check" aria-hidden="true"></span>이름순</a></li>
      </ul>
      <hr class="dc-dd__sep">
      <ul class="dc-dd__list">
        <li><button class="dc-dd__item dc-dd__item--danger" type="button"><span class="dc-dd__check" aria-hidden="true"></span>기본 정렬로 되돌리기</button></li>
      </ul>
    </div>
  </details>
</div>
/* 열린 메뉴는 absolute 라서 미리보기 높이에 안 잡힌다 — 자리를 비워 둔다 */
.dc-dd { min-height: 280px; font-family: var(--dc-font); }
.dc-dd__root { position: relative; display: inline-block; }
.dc-dd__trigger {
  display: inline-flex; align-items: center; gap: var(--dc-2);
  min-height: 40px; padding: 0 var(--dc-3);
  border: 1px solid var(--dc-line-bold); border-radius: var(--dc-r-sm);
  background: var(--dc-surface); color: var(--dc-text);
  font-size: 14px; font-weight: 600; cursor: pointer; list-style: none;
  transition: background var(--dc-fast), border-color var(--dc-fast);
}
.dc-dd__trigger::-webkit-details-marker { display: none; }
.dc-dd__trigger:hover { background: var(--dc-sunken); border-color: var(--dc-text-mute); }
.dc-dd__label { white-space: nowrap; }
.dc-dd__caret { color: var(--dc-text-sub); font-size: 11px; transition: transform var(--dc-fast); }
.dc-dd__root[open] .dc-dd__caret { transform: rotate(180deg); }
.dc-dd__pop {
  position: absolute; top: calc(100% + var(--dc-1)); left: 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-dd__head {
  margin: 0; padding: var(--dc-1) var(--dc-2) var(--dc-2);
  color: var(--dc-text-mute); font-size: 12px; font-weight: 700;
  letter-spacing: .02em; text-transform: none;
}
.dc-dd__list { list-style: none; margin: 0; padding: 0; }
.dc-dd__item {
  display: flex; align-items: center; gap: var(--dc-2);
  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; text-decoration: none;
  cursor: pointer; transition: background var(--dc-fast);
}
.dc-dd__item:hover { background: var(--dc-sunken); }
.dc-dd__item[aria-current="true"] { color: var(--dc-brand-text); font-weight: 700; }
.dc-dd__check { flex: 0 0 16px; width: 16px; color: var(--dc-brand); font-size: 13px; }
.dc-dd__item--danger { color: var(--dc-danger); }
.dc-dd__item--danger:hover { background: var(--dc-danger-soft); }
.dc-dd__sep { height: 1px; margin: var(--dc-2) 0; border: 0; background: var(--dc-line); }

.dc-dd--right { display: flex; justify-content: flex-end; min-height: 320px; }
.dc-dd--right .dc-dd__pop { left: auto; right: 0; }
.dc-dd__iconbtn {
  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);
  font-size: 16px; cursor: pointer; list-style: none;
}
.dc-dd__iconbtn::-webkit-details-marker { display: none; }
.dc-dd__iconbtn:hover { background: var(--dc-sunken); }
.dc-dd__avatar {
  display: grid; place-items: center; width: 28px; height: 28px;
  border-radius: var(--dc-r-full);
  background: var(--dc-brand-soft); color: var(--dc-brand-text);
  font-size: 13px; font-weight: 800;
}
.dc-dd__user { padding: var(--dc-2); }
.dc-dd__username { margin: 0; color: var(--dc-text); font-size: 14px; font-weight: 700; }
.dc-dd__mail { margin: 2px 0 0; color: var(--dc-text-sub); font-size: 12px; }

How to use it

  • Put the current choice in the trigger label — 'Sort: Newest'
  • Past about seven items, split into sections or move to a page of its own
  • Built on details/summary it opens and closes from the keyboard with no script

Watch out for

  • Keep destructive items last and never signal them by color alone
  • Near the right edge, flip the menu to right alignment or it gets clipped

Next