Đến nội dung chính

Biểu mẫu ba bước

Khung để cắt một biểu mẫu dài mà không ai điền hết thành ba phần nhỏ.

Mẫu biểu mẫu

Xem trước trực tiếp

Nguồn

<form class="dc-stf" action="#">
  <header class="dc-stf__bar">
    <button class="dc-stf__back" type="button">
      <span aria-hidden="true">‹</span><span class="dc-sr">뒤로</span>
    </button>
    <h1 class="dc-stf__bartitle">일자리 신청</h1>
    <span class="dc-stf__count">1 / 3</span>
  </header>
  <div class="dc-stf__prog" role="progressbar" aria-label="3단계 중 1단계" aria-valuemin="1" aria-valuemax="3" aria-valuenow="1">
    <span class="dc-stf__fill" style="width:33%"></span>
  </div>
  <ol class="dc-stf__steps">
    <li class="dc-stf__step" aria-current="step">1 기본 정보</li>
    <li class="dc-stf__step">2 희망 조건</li>
    <li class="dc-stf__step">3 확인</li>
  </ol>
  <div class="dc-stf__body">
    <h2 class="dc-stf__h2">이름과 연락처를 알려 주세요</h2>
    <p class="dc-stf__desc">사장님이 연락할 때만 씁니다.</p>
    <div class="dc-stf__field">
      <label class="dc-stf__label" for="dc-stf-name">이름</label>
      <input class="dc-stf__input" id="dc-stf-name" type="text" autocomplete="name" value="김민수" />
    </div>
    <div class="dc-stf__field">
      <label class="dc-stf__label" for="dc-stf-tel">휴대폰 번호</label>
      <input class="dc-stf__input" id="dc-stf-tel" type="tel" inputmode="numeric" autocomplete="tel" placeholder="010-0000-0000" aria-describedby="dc-stf-telhint" />
      <p class="dc-stf__hint" id="dc-stf-telhint">한국에서 쓰는 번호를 넣어 주세요.</p>
    </div>
  </div>
  <div class="dc-stf__bottom">
    <button class="dc-stf__next" type="submit">다음</button>
  </div>
</form>
.dc-stf { display:flex; flex-direction:column; height:600px; overflow:hidden; background:var(--dc-bg); border:1px solid var(--dc-line); border-radius:var(--dc-r-md); font-family:var(--dc-font); }
.dc-stf__bar { flex:0 0 auto; display:flex; align-items:center; gap:var(--dc-1); padding:calc(var(--dc-safe-top) + var(--dc-2)) var(--dc-4) var(--dc-2) var(--dc-2); background:var(--dc-surface); }
.dc-stf__back { 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); font-size:22px; line-height:1; }
.dc-stf__back:active { background:var(--dc-sunken); }
.dc-stf__bartitle { flex:1 1 auto; min-width:0; margin:0; font-size:16px; font-weight:700; color:var(--dc-text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.dc-stf__count { flex:0 0 auto; font-family:var(--dc-mono); font-size:13px; font-weight:700; color:var(--dc-text-sub); }
.dc-stf__prog { flex:0 0 auto; height:4px; background:var(--dc-sunken); }
.dc-stf__fill { display:block; height:100%; border-radius:var(--dc-r-full); background:var(--dc-brand); transition:width var(--dc-slow); }
.dc-stf__steps { flex:0 0 auto; display:flex; gap:var(--dc-2); margin:0; padding:var(--dc-3) var(--dc-4); list-style:none; background:var(--dc-surface); border-bottom:1px solid var(--dc-line); }
.dc-stf__step { flex:1 1 0; min-width:0; font-size:12px; font-weight:700; color:var(--dc-text-mute); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.dc-stf__step[aria-current="step"] { color:var(--dc-brand-text); }
.dc-stf__body { flex:1 1 auto; min-height:0; overflow-y:auto; display:flex; flex-direction:column; gap:var(--dc-4); padding:var(--dc-5) var(--dc-4); }
.dc-stf__h2 { margin:0; font-size:19px; font-weight:800; letter-spacing:-.02em; line-height:1.4; color:var(--dc-text); }
.dc-stf__desc { margin:0; font-size:13px; color:var(--dc-text-sub); }
.dc-stf__field { display:flex; flex-direction:column; gap:var(--dc-2); }
.dc-stf__label { font-size:13px; font-weight:700; color:var(--dc-text-sub); }
.dc-stf__input, .dc-stf__select { width:100%; min-height:48px; padding:0 var(--dc-3); border:1px solid var(--dc-line-field); border-radius:var(--dc-r-sm); background:var(--dc-surface); color:var(--dc-text); font-family:inherit; font-size:16px; }
.dc-stf__input:focus, .dc-stf__select:focus { outline:none; border-color:var(--dc-brand); box-shadow:0 0 0 3px var(--dc-brand-soft); }
.dc-stf__hint { margin:0; font-size:12px; color:var(--dc-text-mute); }
.dc-stf__opts { min-width:0; margin:0; padding:0; border:0; display:flex; flex-direction:column; gap:var(--dc-2); }
.dc-stf__legend { padding:0; margin-bottom:var(--dc-2); font-size:13px; font-weight:700; color:var(--dc-text-sub); }
.dc-stf__opt { display:flex; align-items:center; gap:var(--dc-3); min-height:52px; padding:0 var(--dc-4); border:1px solid var(--dc-line); border-radius:var(--dc-r-sm); background:var(--dc-surface); font-size:15px; color:var(--dc-text); }
.dc-stf__opt:has(.dc-stf__radio:checked) { border-color:var(--dc-brand); background:var(--dc-brand-soft); }
.dc-stf__radio { flex:0 0 auto; width:20px; height:20px; accent-color:var(--dc-brand); }
.dc-stf__rows { margin:0; border:1px solid var(--dc-line); border-radius:var(--dc-r-md); background:var(--dc-surface); overflow:hidden; }
.dc-stf__row { display:flex; align-items:baseline; justify-content:space-between; gap:var(--dc-3); padding:var(--dc-3) var(--dc-4); border-bottom:1px solid var(--dc-line); }
.dc-stf__row:last-child { border-bottom:0; }
.dc-stf__k { margin:0; font-size:13px; color:var(--dc-text-sub); }
.dc-stf__v { margin:0; font-size:15px; font-weight:700; color:var(--dc-text); text-align:right; }
.dc-stf__agree { display:flex; align-items:flex-start; gap:var(--dc-3); min-height:44px; padding:var(--dc-2) 0; }
.dc-stf__check { flex:0 0 auto; width:20px; height:20px; margin-top:2px; accent-color:var(--dc-brand); }
.dc-stf__agreetxt { font-size:14px; line-height:1.6; color:var(--dc-text); }
.dc-stf__bottom { flex:0 0 auto; display:flex; gap:var(--dc-2); padding:var(--dc-3) var(--dc-4) calc(var(--dc-safe-bottom) + var(--dc-3)); background:var(--dc-surface); border-top:1px solid var(--dc-line); }
.dc-stf__prev { flex:0 0 auto; min-width:96px; min-height:52px; border:1px solid var(--dc-line-field); border-radius:var(--dc-r-sm); background:var(--dc-surface); color:var(--dc-text); font-family:inherit; font-size:15px; font-weight:700; }
.dc-stf__prev:active { background:var(--dc-sunken); }
.dc-stf__next { flex:1 1 auto; min-height:52px; border:0; border-radius:var(--dc-r-sm); background:var(--dc-brand); color:var(--dc-text-on); font-family:inherit; font-size:16px; font-weight:700; }
.dc-stf__next:active { background:var(--dc-brand-hi); }

Cách dùng

  • Mỗi bước chỉ hỏi quanh một chủ đề — thông tin của tôi, điều tôi muốn, xác nhận
  • Cho thấy bước hiện tại bằng cả con số và thanh tiến trình
  • Bước cuối không hỏi thêm: nhắc lại câu trả lời và mở đường quay lại sửa
  • Lưu từng bước để đi lui đi tiến không làm trống ô nào

Điểm cần lưu ý

  • Thanh tiến trình cần role=progressbar và aria-valuenow — chỉ màu thì không được đọc
  • Đừng để nút Quay lại xám ở bước một; không có nút còn ít gây nhầm hơn
  • Tên bước phải ngắn đủ để ba tên nằm một dòng — tràn ra sẽ bị cắt bằng dấu ba chấm

Tiếp theo