Sticky bottom bar
Pins the deciding action to the bottom of the screen, so nobody has to reach the end of a long page to act.
Live preview
Source
<div class="dc-stickyshell">
<div class="dc-stickyshell__page">
<p class="dc-stickyshell__line">용접 보조 — 경기 화성</p>
<p class="dc-stickyshell__line">주 5일 · 오전 8시 ~ 오후 5시</p>
<p class="dc-stickyshell__line">기숙사 제공, 점심 제공</p>
<p class="dc-stickyshell__line">E-9 비자로 지원할 수 있습니다.</p>
<p class="dc-stickyshell__line">교육 2주, 교육 기간에도 일당이 나옵니다.</p>
<p class="dc-stickyshell__line">아래로 내려도 바는 자리에 남아 있습니다.</p>
</div>
<div class="dc-stickybar">
<div class="dc-stickybar__info">
<span class="dc-stickybar__label">월급</span>
<strong class="dc-stickybar__price">280만원</strong>
</div>
<div class="dc-stickybar__actions">
<button type="button" class="dc-stickybar__btn dc-stickybar__btn--ghost">저장</button>
<button type="button" class="dc-stickybar__btn">지원하기</button>
</div>
</div>
</div>
.dc-stickyshell { position:relative; display:flex; flex-direction:column; height:300px; overflow:hidden; border:1px solid var(--dc-line); border-radius:var(--dc-r-md); background:var(--dc-bg); font-family:var(--dc-font); }
.dc-stickyshell__page { flex:1 1 auto; overflow-y:auto; padding:var(--dc-4); }
.dc-stickyshell__line { margin:0 0 var(--dc-5); font-size:14px; line-height:1.6; color:var(--dc-text-sub); }
.dc-stickybar { position:sticky; bottom:0; display:flex; align-items:center; justify-content:space-between; gap:var(--dc-4); padding:var(--dc-3) var(--dc-4); padding-bottom:calc(var(--dc-3) + var(--dc-safe-bottom)); border-top:1px solid var(--dc-line); background:var(--dc-surface); box-shadow:var(--dc-sh-2); }
.dc-stickybar__info { display:flex; flex-direction:column; min-width:0; }
.dc-stickybar__label { font-size:12px; color:var(--dc-text-mute); }
.dc-stickybar__price { font-size:17px; font-weight:700; color:var(--dc-text); }
.dc-stickybar__step { font-size:13px; font-weight:600; color:var(--dc-text-sub); }
.dc-stickybar__actions { display:flex; align-items:center; gap:var(--dc-2); flex-shrink:0; }
.dc-stickybar__btn { 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-size:15px; font-weight:700; transition:background var(--dc-fast); }
.dc-stickybar__btn:hover { background:var(--dc-brand-hi); }
.dc-stickybar__btn--ghost { min-width:44px; background:var(--dc-surface); border-color:var(--dc-line-field); color:var(--dc-text); }
.dc-stickybar__btn--ghost:hover { background:var(--dc-sunken); }
.dc-stickybar--single { display:block; }
.dc-stickybar--single .dc-stickybar__btn { width:100%; }
@media (max-width:480px) {
.dc-stickybar { flex-wrap:wrap; }
.dc-stickybar__actions { flex:1 1 auto; }
.dc-stickybar__btn { flex:1 1 auto; padding:0 var(--dc-3); }
}
How to use it
- One button, two at most — a third erases which one is primary
- Don't show the button alone; put the number the decision needs (total, step) beside it
- When the price or the step changes, the bar has to change with it — the bar is a summary
Watch out for
- Add --dc-safe-bottom to the bottom padding, or the home indicator sits on top of the button
- Keep the tap target at 44px or more, and don't make the bar translucent enough to read text through
- Leave bottom padding on the page equal to the bar's height, or the last line hides underneath it