Skip to content

Button

For when the label alone has to tell people what happens after the press.

Actions

Live preview

Source

<button type="button" class="dc-btn">주문하기</button>
.dc-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--dc-2);
  min-height: 44px; padding: 0 var(--dc-5);
  border: 1px solid transparent; border-radius: var(--dc-r-sm);
  background: var(--dc-brand); color: var(--dc-text-on);
  font-family: var(--dc-font); font-size: 15px; font-weight: 600; line-height: 1;
  white-space: nowrap;
  transition: background var(--dc-fast), transform var(--dc-fast);
}
.dc-btn:hover,
.dc-btn.is-hover { background: var(--dc-brand-hi); }
.dc-btn:active,
.dc-btn.is-active { background: var(--dc-brand-hi); transform: translateY(1px); }
.dc-btn[disabled] {
  background: var(--dc-sunken); color: var(--dc-text-mute);
  border-color: var(--dc-line); cursor: not-allowed;
}
.dc-btn[aria-busy="true"] { cursor: progress; }
/* 처리 중에는 눌린 듯 반응하지 않는다 — 한 번 더 눌러도 되는 것처럼 보인다 */
.dc-btn[aria-disabled="true"]:hover,
.dc-btn[aria-disabled="true"]:active { background: var(--dc-brand); transform: none; }
.dc-btn--sm { min-height: 36px; padding: 0 var(--dc-4); font-size: 14px; }
.dc-btn--lg { min-height: 52px; padding: 0 var(--dc-6); font-size: 17px; border-radius: var(--dc-r-md); }
.dc-btn__spinner {
  width: 16px; height: 16px; flex: none; border-radius: var(--dc-r-full);
  border: 2px solid color-mix(in srgb, var(--dc-text-on) 30%, transparent);
  border-top-color: var(--dc-text-on);
  animation: dc-btn-spin .7s linear infinite;
}
@keyframes dc-btn-spin { to { transform: rotate(360deg); } }

How to use it

  • One primary button per screen — two and people hesitate
  • Label the outcome: 'Place order', not 'OK'
  • Switch to the loading state for slow work so it cannot be pressed twice

Watch out for

  • Keep it 44px tall wherever fingers press — the small variant belongs only in dense, mouse-driven toolbars
  • A disabled button with no explanation leaves people stuck

Next