Khung màn hình ứng dụng
Chia màn hình thành thanh trên, phần thân cuộn được và thanh tab, để hai thanh đứng yên khi nội dung chạy.
Xem trước trực tiếp
Nguồn
<div class="dc-shell">
<header class="dc-shell__top">
<h1 class="dc-shell__title">일자리</h1>
<button class="dc-shell__ico" type="button">
<span aria-hidden="true">⋯</span>
<span class="dc-sr">더보기</span>
</button>
</header>
<main class="dc-shell__body">
<p class="dc-shell__note">본문만 스크롤합니다. 위·아래 바는 제자리에 남습니다.</p>
<a class="dc-shell__card" href="#">
<span class="dc-shell__card-title">용접 보조 · 김해</span>
<span class="dc-shell__card-meta">일당 160,000원 · 오늘 마감</span>
</a>
<a class="dc-shell__card" href="#">
<span class="dc-shell__card-title">식품 포장 · 평택</span>
<span class="dc-shell__card-meta">일당 130,000원 · 기숙사 있음</span>
</a>
<a class="dc-shell__card" href="#">
<span class="dc-shell__card-title">물류 상하차 · 인천</span>
<span class="dc-shell__card-meta">일당 140,000원 · 주 5일</span>
</a>
<a class="dc-shell__card" href="#">
<span class="dc-shell__card-title">호텔 객실 정리 · 제주</span>
<span class="dc-shell__card-meta">월급 2,450,000원 · 초보 가능</span>
</a>
<a class="dc-shell__card" href="#">
<span class="dc-shell__card-title">농장 일손 · 나주</span>
<span class="dc-shell__card-meta">일당 120,000원 · 차량 지원</span>
</a>
</main>
<nav class="dc-shell__tabs" aria-label="주요 메뉴">
<a class="dc-shell__tab" href="#" aria-current="page">
<span class="dc-shell__tab-ico" aria-hidden="true">⌂</span>
<span class="dc-shell__tab-lbl">홈</span>
</a>
<a class="dc-shell__tab" href="#">
<span class="dc-shell__tab-ico" aria-hidden="true">⌕</span>
<span class="dc-shell__tab-lbl">검색</span>
</a>
<a class="dc-shell__tab" href="#">
<span class="dc-shell__tab-ico" aria-hidden="true">♡</span>
<span class="dc-shell__tab-lbl">찜</span>
</a>
<a class="dc-shell__tab" href="#">
<span class="dc-shell__tab-ico" aria-hidden="true">◉</span>
<span class="dc-shell__tab-lbl">내 정보</span>
</a>
</nav>
</div>
.dc-shell {
display: flex; flex-direction: column;
height: 560px; overflow: hidden;
background: var(--dc-bg);
border: 1px solid var(--dc-line);
border-radius: var(--dc-r-md);
font-family: var(--dc-font);
}
.dc-shell__top {
flex: 0 0 auto;
display: flex; align-items: center; gap: var(--dc-2);
padding: calc(var(--dc-safe-top) + var(--dc-2)) var(--dc-2) var(--dc-2) var(--dc-4);
background: var(--dc-surface);
border-bottom: 1px solid var(--dc-line);
}
.dc-shell__title {
flex: 1 1 auto; min-width: 0;
font-size: 19px; font-weight: 800; letter-spacing: -.02em;
color: var(--dc-text);
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dc-shell__title--center { text-align: center; font-size: 16px; font-weight: 700; }
.dc-shell__ico {
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: 20px; line-height: 1;
}
.dc-shell__ico:active { background: var(--dc-sunken); }
.dc-shell__body {
flex: 1 1 auto; min-height: 0;
overflow-y: auto; overscroll-behavior: contain;
display: flex; flex-direction: column; gap: var(--dc-3);
padding: var(--dc-4);
background: var(--dc-bg);
}
.dc-shell__note { margin: 0; font-size: 12px; color: var(--dc-text-mute); }
.dc-shell__card {
display: flex; flex-direction: column; gap: var(--dc-1);
min-height: 72px; padding: var(--dc-4);
border: 1px solid var(--dc-line); border-radius: var(--dc-r-md);
background: var(--dc-surface); box-shadow: var(--dc-sh-1);
text-decoration: none;
}
.dc-shell__card:active { background: var(--dc-sunken); }
.dc-shell__card-title { font-size: 15px; font-weight: 700; color: var(--dc-text); }
.dc-shell__card-meta { font-size: 13px; color: var(--dc-text-sub); }
.dc-shell__tabs {
flex: 0 0 auto;
display: flex; align-items: stretch;
padding-bottom: var(--dc-safe-bottom);
background: var(--dc-surface);
border-top: 1px solid var(--dc-line);
}
.dc-shell__tab {
flex: 1 1 0; min-width: 0;
display: flex; flex-direction: column;
align-items: center; justify-content: center; gap: 3px;
min-height: 56px; padding: var(--dc-2) var(--dc-1);
color: var(--dc-text-mute); text-decoration: none;
transition: color var(--dc-fast), background var(--dc-fast);
}
.dc-shell__tab:active { background: var(--dc-sunken); }
.dc-shell__tab[aria-current="page"] { color: var(--dc-brand-text); }
.dc-shell__tab-ico { font-size: 20px; line-height: 1; }
.dc-shell__tab-lbl { font-size: 11px; font-weight: 700; letter-spacing: -.01em; }
.dc-shell__foot {
flex: 0 0 auto;
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-shell__btn {
display: block; width: 100%; min-height: 48px;
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-shell__btn:active { background: var(--dc-brand-hi); }
.dc-shell__form { display: flex; flex-direction: column; gap: var(--dc-2); }
.dc-shell__label { font-size: 13px; font-weight: 700; color: var(--dc-text-sub); }
.dc-shell__input {
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-size: 15px;
}
Cách dùng
- Chỉ cho phần thân cuộn, đừng cuộn cả trang — thanh tab sẽ bị kéo theo
- Thanh trên nói bạn đang ở đâu, thanh tab nói bạn có thể đi đâu; không trộn hai việc đó
- Màn hình chỉ có một việc cần xong, như biểu mẫu, thì bỏ thanh tab và gắn một nút cố định ở dưới
Điểm cần lưu ý
- Thiếu --dc-safe-top và --dc-safe-bottom thì tai thỏ và vạch home sẽ che nội dung
- Đặt chiều cao theo dvh thay vì vh, nếu không hai thanh sẽ nhảy khi thanh địa chỉ thu lại
- Nút chỉ có biểu tượng phải kèm tên trong thẻ dc-sr