본문 바로가기
명함 만들기 캐릭터 모음 16가지 디자인 · PNG / SVG / PDF

하단 시트

화면을 떠나지 않고 한 가지만 고르거나 채워야 할 때, 아래에서 올라와 본문 일부를 덮는 조각.

오버레이

실제 미리보기

출처

<div class="dc-bs-stage">
  <div class="dc-bs-behind" aria-hidden="true">
    <div class="dc-bs-behind__bar"></div>
    <div class="dc-bs-behind__line"></div>
    <div class="dc-bs-behind__line"></div>
  </div>
  <div class="dc-bs-scrim" aria-hidden="true"></div>
  <section class="dc-bs" role="dialog" aria-modal="true" aria-labelledby="dc-bs-t">
    <span class="dc-bs__grab" aria-hidden="true"></span>
    <div class="dc-bs__head">
      <h2 class="dc-bs__title" id="dc-bs-t">배송 방법 고르기</h2>
      <button class="dc-bs__close" type="button">
        <span class="dc-sr">닫기</span>
        <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6.5 6.5l11 11M17.5 6.5l-11 11" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>
      </button>
    </div>
    <div class="dc-bs__body">
      <label class="dc-bs__opt">
        <input class="dc-bs__radio" type="radio" name="dc-bs-ship" checked>
        <span class="dc-bs__opt-main">
          <span class="dc-bs__opt-name">일반 배송</span>
          <span class="dc-bs__opt-desc">9월 14일(월) 도착 예정</span>
        </span>
        <span class="dc-bs__opt-price">무료</span>
      </label>
      <label class="dc-bs__opt">
        <input class="dc-bs__radio" type="radio" name="dc-bs-ship">
        <span class="dc-bs__opt-main">
          <span class="dc-bs__opt-name">새벽 배송</span>
          <span class="dc-bs__opt-desc">내일 오전 7시 전 도착</span>
        </span>
        <span class="dc-bs__opt-price">3,000원</span>
      </label>
      <label class="dc-bs__opt">
        <input class="dc-bs__radio" type="radio" name="dc-bs-ship">
        <span class="dc-bs__opt-main">
          <span class="dc-bs__opt-name">매장에서 받기</span>
          <span class="dc-bs__opt-desc">성수점 · 오늘 오후 6시부터</span>
        </span>
        <span class="dc-bs__opt-price">무료</span>
      </label>
    </div>
    <div class="dc-bs__foot">
      <button class="dc-bs__cta" type="button">이 방법으로 받기</button>
    </div>
  </section>
</div>
.dc-bs-stage {
  position: relative; overflow: hidden;
  height: 520px;
  background: var(--dc-bg);
  border-radius: var(--dc-r-md);
  font-family: var(--dc-font);
}
.dc-bs-behind { padding: calc(var(--dc-safe-top) + var(--dc-6)) var(--dc-5) 0; }
.dc-bs-behind__bar { width: 56%; height: 20px; border-radius: var(--dc-r-full); background: var(--dc-sunken); }
.dc-bs-behind__line { height: 11px; margin-top: var(--dc-3); border-radius: var(--dc-r-full); background: var(--dc-sunken); }
.dc-bs-behind__line:last-child { width: 64%; }
.dc-bs-scrim { position: absolute; inset: 0; background: var(--dc-overlay); }
.dc-bs {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column;
  max-height: 88%;
  background: var(--dc-surface);
  border-top: 1px solid var(--dc-line);
  border-radius: var(--dc-r-lg) var(--dc-r-lg) 0 0;
  box-shadow: var(--dc-sh-3);
}
.dc-bs__grab {
  display: block; width: 36px; height: 4px;
  margin: var(--dc-2) auto 0;
  border-radius: var(--dc-r-full);
  background: var(--dc-line-bold);
}
.dc-bs__head {
  display: flex; align-items: center; gap: var(--dc-2);
  padding: var(--dc-3) var(--dc-3) var(--dc-3) var(--dc-5);
}
.dc-bs__title {
  flex: 1 1 auto; margin: 0;
  font-size: 16px; font-weight: 700; line-height: 1.4;
  color: var(--dc-text);
}
.dc-bs__close {
  flex: 0 0 auto;
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border: 0; border-radius: var(--dc-r-full);
  background: transparent; color: var(--dc-text-sub);
}
.dc-bs__close svg { width: 22px; height: 22px; }
.dc-bs__close:active { background: var(--dc-sunken); }
.dc-bs__body { padding: 0 var(--dc-5) var(--dc-4); }
.dc-bs__body--scroll { overflow-y: auto; -webkit-overflow-scrolling: touch; }
.dc-bs__sec {
  margin: var(--dc-4) 0 var(--dc-2);
  font-size: 12px; font-weight: 700; letter-spacing: .02em;
  color: var(--dc-text-mute);
}
.dc-bs__sec:first-child { margin-top: 0; }
.dc-bs__opt {
  display: flex; align-items: center; gap: var(--dc-3);
  min-height: 56px; padding: var(--dc-2) 0;
  border-bottom: 1px solid var(--dc-line);
  cursor: pointer;
}
.dc-bs__opt:last-child { border-bottom: 0; }
.dc-bs__radio {
  flex: 0 0 auto;
  width: 22px; height: 22px; margin: 0;
  accent-color: var(--dc-brand);
}
.dc-bs__opt-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.dc-bs__opt-name { font-size: 14px; font-weight: 600; color: var(--dc-text); }
.dc-bs__opt-desc { font-size: 12px; line-height: 1.5; color: var(--dc-text-sub); }
.dc-bs__opt-price { flex: 0 0 auto; font-size: 13px; font-weight: 700; color: var(--dc-text); }
.dc-bs__radio:checked ~ .dc-bs__opt-main .dc-bs__opt-name { color: var(--dc-brand-text); }
.dc-bs__chips { display: flex; flex-wrap: wrap; gap: var(--dc-2); }
.dc-bs__chip {
  position: relative;
  display: inline-flex; align-items: center;
  min-height: 44px; padding: 0 var(--dc-4);
  border: 1px solid var(--dc-line-field); border-radius: var(--dc-r-full);
  font-size: 13px; font-weight: 600; color: var(--dc-text-sub);
  cursor: pointer;
  transition: background var(--dc-fast), border-color var(--dc-fast), color var(--dc-fast);
}
.dc-bs__chip input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.dc-bs__chip input:checked ~ span { color: var(--dc-brand-text); }
.dc-bs__chip:has(input:checked) { border-color: var(--dc-brand); background: var(--dc-brand-soft); }
.dc-bs__chip:focus-within { outline: 2px solid var(--dc-brand); outline-offset: 2px; }
.dc-bs__foot {
  display: flex; gap: var(--dc-2);
  padding: var(--dc-3) var(--dc-5) calc(var(--dc-4) + var(--dc-safe-bottom));
  border-top: 1px solid var(--dc-line);
  background: var(--dc-surface);
}
.dc-bs__cta {
  flex: 1 1 auto; min-height: 50px; padding: 0 var(--dc-4);
  border: 0; border-radius: var(--dc-r-md);
  background: var(--dc-brand); color: var(--dc-text-on);
  font-size: 15px; font-weight: 700;
  transition: background var(--dc-fast);
}
.dc-bs__cta:active { background: var(--dc-brand-hi); }
.dc-bs__ghost {
  flex: 0 0 auto; min-width: 92px; min-height: 50px; padding: 0 var(--dc-4);
  border: 1px solid var(--dc-line-field); border-radius: var(--dc-r-md);
  background: var(--dc-surface); color: var(--dc-text);
  font-size: 15px; font-weight: 600;
}
.dc-bs__ghost:active { background: var(--dc-sunken); }

이렇게 씁니다

  • 뒤 본문이 계속 보여야 뜻이 통할 때 쓴다. 그럴 필요가 없으면 전체 화면 모달이 맞다
  • 선택지가 다섯 개를 넘으면 본문만 스크롤시키고 제목과 확정 버튼은 고정한다
  • 시트 밖을 눌러 닫히게 하되, 고른 값이 사라지는 시트면 한 번 묻는다
  • 높이는 화면의 90%를 넘기지 않는다 — 뒤가 안 보이면 모달과 구별되지 않는다

주의할 점

  • 확정 버튼 영역에 --dc-safe-bottom 을 빼면 홈 바가 버튼을 가린다
  • 손잡이만 닫는 길로 두지 마라 — 닫기 버튼을 같이 둔다
  • 열릴 때 포커스를 시트 안으로 옮기고 뒤 본문은 낭독기에서 가린다

다음에 볼 것