[Series 100 Bài Học HTML/CSS Thực Chiến - Bài 03]: Làm Chủ Flexbox Dàn Trang Top Navbar Shopee & Tuyệt Chiêu Vẽ Vạch Ngăn Cách Bằng ::after
Chào mừng anh em đã đi tới Bài 03 của chuỗi 100 Bài Học Làm Chủ HTML/CSS Qua Dự Án Clone Shopee!
Sau Bài 02, chúng ta đã có một phần nền màu cam rực rỡ trên Header và xóa sạch những khoảng trắng thừa thãi của trình duyệt. Tuy nhiên, nếu nhìn vào khu vực Top Navbar (thanh điều hướng trên cùng chứa Kênh Người Bán, Tải ứng dụng, Đăng Ký, Đăng Nhập), bạn sẽ thấy một vấn đề lớn: Tất cả các mục đang xếp chồng dọc lên nhau từ trên xuống dưới, trong khi giao diện thật của Shopee lại nằm trên cùng một hàng ngang (một cụm dạt sang trái, một cụm dạt sang phải).
Trong bài học hôm nay, chúng ta sẽ giải quyết triệt để bài toán này bằng vũ khí dàn trang quan trọng bậc nhất của CSS hiện đại: Flexbox (display: flex), đồng thời học một thủ thuật cực kỳ tinh tế của các kỹ sư Frontend: dùng Pseudo-element ::after để vẽ các vạch đứng ngăn cách giữa các mục menu mà không làm "bẩn" cấu trúc HTML!
1. Tại sao các thẻ <ul>, <li> lại tự động rớt dòng?
Trong HTML, các thẻ như <div>, <p>, <ul>, <li>, <header>, <section> mặc định mang kiểu hiển thị là display: block (phần tử khối). Đặc tính cố hữu của một thẻ block là luôn chiếm trọn 100% chiều ngang của khung chứa nó, dẫn đến việc phần tử tiếp theo bắt buộc phải bị đẩy xuống dòng mới.
Ngày xưa, các lập trình viên thường dùng float: left / right hoặc display: inline-block để ép chúng nằm ngang, nhưng cách đó cực kỳ dễ vỡ giao diện và rất khổ sở khi muốn căn giữa theo chiều dọc. Giờ đây, chúng ta có Flexbox.
2. Bản chất của Flexbox trong 2 phút: Hệ trục Main Axis & Cross Axis
Để làm chủ Flexbox, bạn chỉ cần nhớ quy tắc cốt lõi: Khi bạn gắn thuộc tính display: flex vào thẻ cha (Flex Container), lập tức tất cả các thẻ con trực tiếp bên trong nó (Flex Items) sẽ tự động xếp hàng ngang và xoay quanh 2 trục tọa độ:

Hãy nhìn vào sơ đồ trên: khi flex-direction ở trạng thái mặc định là row (hàng ngang), hai trục của Flexbox hoạt động như sau:
| Tên trục / Thuộc tính | Hướng mặc định (row) |
Công dụng thực chiến trên Top Navbar Shopee |
|---|---|---|
| Main Axis (Trục chính) | Nằm ngang (Trái Phải) | Dùng thuộc tính justify-content để điều khiển khoảng cách ngang. Cụ thể: dùng space-between để đẩy cụm menu trái sang sát mép trái, cụm menu phải sang sát mép phải. |
| Cross Axis (Trục vuông góc) | Nằm dọc (Trên Dưới) | Dùng thuộc tính align-items để căn chỉnh vị trí dọc. Cụ thể: dùng center để mọi chữ và icon tự động nằm chính giữa chiều cao 34px của thanh Navbar. |
3. Tuyệt chiêu vẽ vạch ngăn cách (|) bằng Pseudo-element ::after
Nếu nhìn kỹ thanh Top Navbar của Shopee, giữa chữ "Kênh Người Bán" và "Trở thành Người bán Shopee" có một vạch kẻ dọc mảnh màu trắng mờ.
-
Cách làm của người mới: Gõ thẳng ký tự gạch đứng
<li>Kênh Người Bán |</li>hoặc chèn thêm thẻ<span class="divider">|</span>vào HTML. Cách này làm rác HTML, trình đọc màn hình (Screen Reader) sẽ đọc luôn cả chữ "vertical bar", và rất khó căn chỉnh chiều cao của vạch kẻ. -
Cách làm của chuyên gia: Sử dụng phần tử giả
::afterkết hợp với định vị tuyệt đối (position: absolute). Chúng ta tạo ra một "bóng ma" có chiều rộng1px, chiều cao12pxnằm ngay sát mép phải của từng thẻ<li>.
4. Thực hành: Code hoàn chỉnh thanh Top Navbar Shopee
Bước 1: Cập nhật cấu trúc HTML chuẩn chỉnh trong index.html
Hãy mở file index.html, tìm đến thẻ <header class="shopee-header"> và cập nhật lại khu vực .top-navbar.
(Lưu ý: Chúng ta bọc thêm thẻ <div class="grid-container"> vào trong <header> để nội dung Header luôn nằm gọn trong khung 1200px thẳng hàng với phần thân trang, và gắn class .nav-item--separate cho những mục cần có vạch ngăn cách bên phải).
HTML
<!-- 1. VÙNG ĐẦU TRANG (HEADER) -->
<header class="shopee-header">
<div class="grid-container">
<!-- Thanh điều hướng phía trên (Top Navbar) -->
<nav class="top-navbar">
<!-- Cụm menu bên trái -->
<ul class="nav-list">
<li class="nav-item nav-item--separate">
<a href="#" class="nav-link">Kênh Người Bán</a>
</li>
<li class="nav-item nav-item--separate">
<a href="#" class="nav-link">Trở thành Người bán Shopee</a>
</li>
<li class="nav-item nav-item--separate">
<a href="#" class="nav-link">Tải ứng dụng</a>
</li>
<li class="nav-item">
<span class="nav-title-no-pointer">Kết nối</span>
</li>
</ul>
<!-- Cụm menu bên phải -->
<ul class="nav-list">
<li class="nav-item">
<a href="#" class="nav-link">Thông Báo</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">Hỗ Trợ</a>
</li>
<li class="nav-item nav-item--separate">
<a href="#" class="nav-link nav-link--strong">Đăng Ký</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link nav-link--strong">Đăng Nhập</a>
</li>
</ul>
</nav>
<!-- Khu vực Logo, Tìm kiếm và Giỏ hàng (Sẽ làm ở Bài 05) -->
<div class="header-with-search">
<!-- Giữ nguyên code cũ từ Bài 01 -->
</div>
</div>
</header>
Bước 2: Viết CSS dàn trang Flexbox và vẽ vạch ::after trong main.css
Mở file ./assets/css/main.css và bổ sung đoạn code dưới đây ngay bên dưới class .shopee-header:
CSS
/* ./assets/css/main.css */
/* --- KHU VỰC TOP NAVBAR --- */
.top-navbar {
height: var(--navbar-height); /* 34px đã khai báo ở base.css */
display: flex;
justify-content: space-between; /* Đẩy 2 thẻ <ul> ra 2 đầu trái - phải */
align-items: center; /* Căn giữa theo chiều dọc */
}
.nav-list {
display: flex; /* Giúp các thẻ <li> bên trong xếp thành hàng ngang */
align-items: center;
}
.nav-item {
position: relative; /* Làm gốc tọa độ cho vạch ngăn cách ::after */
margin: 0 0.8rem; /* Tạo khoảng cách 8px trái/phải giữa các mục */
}
/* Xóa khoảng cách thừa ở mục đầu tiên bên trái và mục cuối cùng bên phải */
.nav-list:first-child .nav-item:first-child {
margin-left: 0;
}
.nav-list:last-child .nav-item:last-child {
margin-right: 0;
}
.nav-link,
.nav-title-no-pointer {
font-size: 1.3rem; /* Cỡ chữ 13px chuẩn Topbar Shopee */
color: var(--white-color);
font-weight: 300; /* Nét chữ mảnh, thanh thoát */
transition: opacity 0.2s ease; /* Tạo hiệu ứng mờ dần mượt mà khi di chuột */
}
/* Hiệu ứng mờ đi khi di chuột vào link (trừ chữ "Kết nối") */
.nav-link:hover {
color: rgba(255, 255, 255, 0.7);
}
/* In đậm cho nút Đăng Ký / Đăng Nhập */
.nav-link--strong {
font-weight: 500;
}
/* Chữ "Kết nối" chỉ là nhãn văn bản, không cho phép bấm vào */
.nav-title-no-pointer {
cursor: text;
}
/* TUYỆT CHIÊU: Vẽ vạch ngăn cách dọc bằng Pseudo-element ::after */
.nav-item--separate::after {
content: ""; /* Bắt buộc phải có thuộc tính content thì ::after mới hiện */
display: block;
position: absolute;
width: 1px; /* Độ dày vạch 1px */
height: 1.2rem; /* Chiều cao vạch 12px */
background-color: hsla(0, 0%, 100%, 0.22); /* Màu trắng trong suốt 22% chuẩn Shopee */
right: -0.9rem; /* Đẩy vạch ra giữa khe hở của 2 thẻ <li> */
top: 50%; /* Đưa đỉnh của vạch xuống chính giữa (50%) chiều cao thẻ <li> */
transform: translateY(-50%); /* Kéo ngược vạch lên 50% chiều cao của chính nó để căn tâm tuyệt đối */
}

5. Giải mã dòng code: 3 Chi tiết "ăn tiền" của dân chuyên nghiệp
-
Flexbox lồng nhau (Nested Flexbox):
-
Chúng ta đặt
display: flexlần 1 ở.top-navbarđể tách 2 cụm<ul class="nav-list">sang 2 đầu màn hình. -
Sau đó, chúng ta đặt
display: flexlần 2 ở chính.nav-listđể ép các thẻ<li class="nav-item">bên trong từng cụm xếp thành hàng ngang. Đây là mô hình Flexbox trong Flexbox xuất hiện ở 90% các thanh điều hướng thực tế.
-
-
Công thức căn giữa tuyệt đối
top: 50%+transform: translateY(-50%):-
Khi bạn dùng
position: absolutecho vạch ngăn cách::after, nếu chỉ viếttop: 50%, trình duyệt sẽ đặt mép trên cùng của vạch kẻ tại điểm giữa của dòng chữ (làm vạch kẻ bị lệch xuống dưới). -
Kết hợp thêm
transform: translateY(-50%)sẽ kéo vạch kẻ dịch ngược lên trên đúng bằng một nửa chiều cao của chính nó (6px), giúp vạch kẻ nằm chính tâm 100% bất kể chữ cao hay thấp!
-
-
Bộ chọn
:first-childvà:last-child:- Khi cho
.nav-itemcómargin: 0 0.8rem, chữ "Kênh Người Bán" ở ngoài cùng bên trái cũng bị thụt vào8px, làm nó lệch trục dọc so với Logo Shopee bên dưới. Dùng:first-childđể xóamargin-left: 0giúp mép trái của chữ thẳng tắp tuyệt đối với khung1200px.
- Khi cho
6. Bài tập thử thách & Hẹn gặp ở Bài 04!
Hãy lưu lại toàn bộ file và nhấn F5 trên trình duyệt! Bạn sẽ thấy thanh Top Navbar của Shopee hiện lên sắc nét đến từng pixel: chữ mảnh tinh tế, di chuột vào có hiệu ứng mờ nhẹ, và các vạch ngăn cách đứng thẳng hàng hoàn hảo.
Thử thách nhỏ trước khi sang Bài 04:
-
Mở Chrome DevTools (F12), chọn thẻ
<nav class="top-navbar">, thử đổi giá trịjustify-content: space-betweenlần lượt thànhcenter,flex-start,space-around,space-evenlyđể tận mắt quan sát cách các cụm menu di chuyển. -
Thử tắt dòng
content: "";trong.nav-item--separate::afterxem điều gì xảy ra với các vạch ngăn cách nhé!
Ở Bài 04, chúng ta sẽ học cách nhúng thư viện Icon (FontAwesome) và Font chữ chuẩn (Roboto) vào dự án để thêm biểu tượng Facebook, Instagram cạnh chữ "Kết nối", thêm quả chuông "Thông báo", và đặc biệt là dựng Hộp thoại mã QR Tải ứng dụng tự động hiện ra khi di chuột vào!
All rights reserved