CSS Tabs rất tuyệt để hiển thị thông tin liên quan tại một nơi dễ navigate. Chúng trông như tab phân chia trong hộp công thức hoặc bìa tài liệu. Ví dụ website dùng tab navigation:
- Southwest Airlines: tab cho check-in, book flight, thêm khách sạn.
- Enterprise: tab cho thuê/mua xe, tìm hiểu dịch vụ khác.
Quan sát 2 site này, suy nghĩ: Ưu điểm của UI component này? Giải quyết vấn đề gì? Phù hợp cho loại thông tin nào?
Khi cần UI structure tổ chức text/info thành các component có ý nghĩa, hiển thị mà không chiếm nhiều không gian → tabbed navigation là lựa chọn khôn ngoan. Sẽ nói sâu hơn về tab navigation với JS, jQuery, Bootstrap, nhưng có implementation chỉ cần HTML + CSS thuần. Xem setup:
Setup HTML:
Boilerplate HTML với container trong body làm main container. Class đặt tên tùy ý, ví dụ class="tabs":
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Tabs</title>
<style> /* CSS sau */ </style>
</head>
<body>
<div class="tabs"></div>
</body>
</html>
Bên trong <div class="tabs">, thêm 4 <div class="tab"> – mỗi tab chứa input, label, content:
<div class="tabs">
<div class="tab">
<input type="radio" id="tab-1" name="tab-group-1" checked/>
<label for="tab-1">Label 1</label>
<div class="content">Our content will go here</div>
</div>
<div class="tab">
<input type="radio" id="tab-2" name="tab-group-1" checked/>
<label for="tab-2">Label 2</label>
<div class="content gryffindor">Our content will go here</div>
</div>
<div class="tab">Thử 2 tab còn lại! Tuân thủ convention class/id...</div>
<div class="tab"></div>
</div>
Bên trong class content là nội dung. Dùng content liên quan cho mỗi tab.
Bắt Đầu CSS:
Viết CSS từ container lớn nhất đến nhỏ nhất. Tối thiểu cần:
- Wildcard selector:
box-sizing: border-box. - Main container (
.tabs):display: flex(tab nằm ngang hàng) +position: relative(làm boundary chứa content).
Lúc này thấy 4 block text với radio button và content. Cần hiện block checked, ẩn các block khác.
- Style label trong
.tab:- Border 1px solid màu bất kỳ.
- Padding: 5px 10px – khoảng cách quanh text label.
- Border-radius: 10px 10px 0 0 – trông như tab truyền thống.
Kiểm tra: label có radio button tròn bên trái. Cần ẩn phần tròn radio nhưng giữ checked attribute.
- Ẩn radio button:
.tab [type='radio'] { display: none; }.
Xử lý content để chỉ hiện 1 tab tại một thời điểm:
- Chọn content div:
position: absolute. Với absolute, div đặt đâu cũng được trong parent relative. Dùng top/right/left/bottom để position. Setleft: 0; right: 0. Thêm border và background color không transparent. - z-index cho tab selected:
[type='radio']:checked ~ label ~ .content { z-index: 1; }. Dấu "~" = sibling selector: content xuất hiện sau label xuất hiện sau radio checked. - Đánh dấu tab active:
[type='radio']:checked ~ labelvới background color khác.
Bây giờ click từng tab → chuyển đổi thành công, không thấy content panel khác. Đủ để tab navigation chạy. Thử tùy chỉnh CSS!
Implementation hoàn chỉnh:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Tabs</title>
<style>
* { box-sizing: border-box; }
body { font-family: 'Roboto'; }
.tabs { max-width: 700px; min-height: 100px; margin: 25px 0; width: 100%; display: flex; position: relative; }
.tab label { padding: 5px 10px; border: 1px solid #ccc; cursor: pointer; border-radius: 10px 10px 0 0; }
.tab [type='radio'] { display: none; }
h3 { margin: 10px 40px; }
ul { list-style-type: none; }
.content { padding: 10px; border-radius: 0px 10px 10px 10px; position: absolute; left: 0; right: 0; background: white; border: 1px solid #ccc; }
[type='radio']:checked ~ label ~ .content { z-index: 1; }
[type="radio"]:checked ~ label { background: lightgrey; }
/* Color scheme tabs (Harry Potter theme) */
[type='radio']:checked ~ #gryffindor { background: #ec9086; color: #241806; }
[type='radio']:checked ~ #ravenclaw { background: #3054ca; color: #241806; }
[type='radio']:checked ~ #slytherin { background: #089714; color: #252525; }
[type='radio']:checked ~ #hufflepuff { background: #f0d695; color: #372e29; }
[type='radio'] ~ #slytherin { background: #033807; color: #aaaaaa; }
[type='radio'] ~ #hufflepuff { background: #f0c75e; color: #372e29; }
[type='radio'] ~ #gryffindor { background: #9c1203; color: #e3a000; }
[type='radio'] ~ #ravenclaw { background: #0e1a40; color: #946b2d; }
.gryffindor { background: #9c1203; color: #e3a000; }
.slytherin { background: #033807; color: #aaaaaa; }
.hufflepuff { background: #f0c75e; color: #372e29; }
.ravenclaw { background: #0e1a40; color: #946b2d; }
</style>
</head>
<body>
<div class="tabs">
<div class="tab">
<input type="radio" id="tab-1" name="tab-group-1" checked/>
<label id="gryffindor" for="tab-1">Gryffindor</label>
<div class="content gryffindor">
<h3>HP Chars in Gryffindor</h3>
<ul class="gryffindor-students">
<li>Harry Potter</li> <li>Hermione Grainger</li> <li>Ron Weasley</li>
<li>Albus Dumbledore</li> <li>Katie Bell</li> <li>Neville Longbottom</li>
</ul>
</div>
</div>
<div class="tab">
<input type="radio" id="tab-2" name="tab-group-1"/>
<label id="slytherin" for="tab-2">Slytherin</label>
<div class="content slytherin"> ... </div>
</div>
<div class="tab">
<input type="radio" id="tab-3" name="tab-group-1"/>
<label for="tab-3" id="ravenclaw">Ravenclaw</label>
<div class="content ravenclaw"> ... </div>
</div>
<div class="tab">
<input type="radio" id="tab-4" name="tab-group-1">
<label for="tab-4" id="hufflepuff">Hufflepuff</label>
<div class="content hufflepuff"> ... </div>
</div>
</div>
</body>
</html>