[Series 100 Bài Học HTML/CSS Thực Chiến - Bài 10]: Thiết Kế Nút Điều Hướng Slider (Prev / Next) Ẩn Hiện Thông Minh & Dãy Chấm Tròn Phân Trang (Pagination Dots) Trên Hero Banner Shopee
Chào mừng anh em đã cán mốc Bài 10 — cột mốc tròn trĩnh đầu tiên trong chuỗi 100 Bài Học Làm Chủ HTML/CSS Qua Dự Án Clone Shopee!
Ở Bài 09, chúng ta đã dùng CSS Grid (2fr 1fr) để dựng xong bộ khung bất đối xứng cho cụm 3 tấm Banner quảng cáo. Tuy nhiên, tấm Banner lớn bên trái (.hero-banner-main) hiện tại mới chỉ là một bức ảnh tĩnh đơn điệu. Trên trang chủ Shopee thực tế, đây là một Carousel Slider (Băng chuyền hình ảnh) cực kỳ sống động với 2 thành phần điều khiển đặc trưng nằm đè trực tiếp lên mặt tấm ảnh:
-
Hai nút mũi tên Trái / Phải (
Prev / Next Buttons): Bình thường hoàn toàn tàng hình để không che khuất hình ảnh khuyến mãi. Chỉ khi nào người dùng đưa chuột vào vùng Banner lớn, hai nút màu đen bán trong suốt này mới lập tức lộ diện ở hai mép trái và phải! -
Dãy chấm tròn phân trang (
Pagination Dots): Nằm căn giữa ở sát mép dưới của Banner, trong đó chấm tròn đại diện cho bức ảnh đang hiển thị (active) sẽ đổi sang màu Cam Shopee rực rỡ.
Trong Bài 10 hôm nay, chúng ta sẽ làm chủ kỹ thuật Định vị nhiều lớp chồng lên ảnh (position: absolute trên nền position: relative), cách bo góc bất đối xứng từng cạnh (border-top-right-radius) và hiệu ứng ẩn hiện mượt mà bằng opacity kết hợp transition!
1. Nguyên lý đặt các nút điều khiển "nổi" đè lên mặt ảnh Banner
Khi bạn chèn một thẻ <img class="hero-banner-img"> cao 235px vào trong khung .hero-banner-main, bức ảnh đã chiếm trọn 100% diện tích của khung. Nếu bạn viết tiếp thẻ <button> (nút mũi tên) và thẻ <ul> (dãy chấm tròn) ở bên dưới thẻ <img>, theo luồng bình thường, chúng sẽ bị đẩy rớt xuống dưới đáy bức ảnh (và bị overflow: hidden cắt mất tiêu!).
Để ép các nút mũi tên và dãy chấm tròn nằm đè lên trên bề mặt bức ảnh, chúng ta áp dụng quy tắc "Cha relative — Con absolute":

Hãy nhìn vào sơ đồ trên: Khi thẻ cha (ở đây là .hero-banner-main) được khai báo position: relative, toàn bộ 4 cạnh top, right, bottom, left của tấm Banner sẽ trở thành hệ quy chiếu tọa độ cho các thẻ con mang position: absolute bên trong nó:
-
Nút mũi tên Trái (
Prev): Đặtposition: absolute; left: 0; top: 50%; transform: translateY(-50%);Bám dính sát mép trái và nằm chính giữa chiều cao tấm ảnh. -
Nút mũi tên Phải (
Next): Đặtposition: absolute; right: 0; top: 50%; transform: translateY(-50%);Bám dính sát mép phải và nằm chính giữa chiều cao tấm ảnh. -
Dãy chấm tròn (
Pagination Dots): Đặtposition: absolute; bottom: 1.2rem; left: 50%; transform: translateX(-50%);Nằm cách đáy ảnh12pxvà căn chính giữa theo chiều ngang!
2. Tại sao ẩn/hiện nút bấm khi Hover phải dùng opacity thay vì display: none?
Ở các bài trước, khi làm hộp thoại QR Code hay Thông Báo, chúng ta dùng display: none và khi :hover thì đổi thành display: block. Tuy nhiên, với 2 nút mũi tên trên Banner, nếu bạn dùng display: none, bạn sẽ không thể dùng transition để làm hiệu ứng hiện dần mượt mà được (vì thuộc tính display chỉ có 2 trạng thái bật/tắt tức thời, không có trạng thái trung gian).
Để nút bấm hiện lên êm ái trong 0.25 giây khi rê chuột vào Banner, các kỹ sư Frontend kết hợp bộ đôi opacity và visibility (hoặc pointer-events):
Trạng thái của .hero-banner-main |
Giá trị opacity của nút bấm | Hiệu ứng thị giác & Tương tác |
|---|---|---|
| Bình thường (Chưa rê chuột vào Banner) |
opacity: 0; |
Nút mũi tên trong suốt 100%, nhường trọn không gian cho ảnh quảng cáo. |
Khi :hover vào .hero-banner-main |
opacity: 1; |
Nút mũi tên hiện rõ dần lên trong 0.25s nhờ transition: opacity 0.25s ease. |
Khi :hover trực tiếp vào chính nút mũi tên |
Nền đậm lên từ rgba(0,0,0,0.18) rgba(0,0,0,0.4) |
Báo hiệu rõ ràng cho người dùng biết nút đã sẵn sàng để click! |
3. Thực hành: Code Nút Điều Hướng & Dãy Chấm Tròn Cho Hero Banner
Bước 1: Bổ sung HTML nút Prev/Next và Pagination Dots vào index.html
Hãy mở file index.html, tìm đến khối <!-- Ô 1: Banner Slider Lớn bên trái --> (.hero-banner-main) mà chúng ta đã tạo ở Bài 09 và nâng cấp nó như sau:
HTML
<!-- Ô 1: Banner Slider Lớn bên trái (Chiếm 2/3 chiều ngang & Gộp 2 dòng dọc) -->
<div class="hero-banner-main">
<!-- Ảnh quảng cáo chính -->
<a href="#" class="hero-banner-link">
<img src="https://placehold.co/800x235/ee4d2d/ffffff?text=SI%C3%8AU+SALE+11.11+-+GI%E1%BA%A2M+%C4%90%E1%BA%BEN+50%25+(800x235)" alt="Siêu Sale Shopee" class="hero-banner-img">
</a>
<!-- 1. NÚT MŨI TÊN LÙI (PREV BUTTON) - Bám sát mép trái -->
<button class="slider-btn slider-btn--prev" aria-label="Ảnh trước">
<i class="fa-solid fa-chevron-left"></i>
</button>
<!-- 2. NÚT MŨI TÊN TIẾN (NEXT BUTTON) - Bám sát mép phải -->
<button class="slider-btn slider-btn--next" aria-label="Ảnh tiếp theo">
<i class="fa-solid fa-chevron-right"></i>
</button>
<!-- 3. DÃY CHẤM TRÒN PHÂN TRANG (PAGINATION DOTS) - Nằm giữa đáy Banner -->
<ul class="slider-dots">
<li class="slider-dot slider-dot--active"></li>
<li class="slider-dot"></li>
<li class="slider-dot"></li>
<li class="slider-dot"></li>
<li class="slider-dot"></li>
<li class="slider-dot"></li>
</ul>
</div>
Bước 2: Viết CSS định vị và tạo hiệu ứng Hover trong ./assets/css/main.css
Mở file main.css, tìm đến khu vực /* --- CHƯƠNG 2: KHU VỰC HERO BANNER --- */ và bổ sung đoạn code dưới đây ngay bên dưới .hero-banner-sub:hover .hero-banner-img:
CSS
/* Bổ sung vào ./assets/css/main.css */
/* --- NÚT MŨI TÊN ĐIỀU HƯỚNG SLIDER (PREV / NEXT BUTTONS) --- */
.slider-btn {
position: absolute;
top: 50%;
transform: translateY(-50%); /* Căn nút nằm chính giữa chiều dọc của Banner */
width: 3.5rem; /* Rộng 35px chuẩn Shopee */
height: 6rem; /* Cao 60px (Hình chữ nhật đứng) */
background-color: rgba(0, 0, 0, 0.18); /* Màu đen bán trong suốt nhẹ nhàng */
color: var(--white-color);
font-size: 1.8rem;
display: flex;
align-items: center;
justify-content: center;
z-index: var(--z-elevate); /* Nổi lên trên mặt tấm ảnh */
/* Mặc định tàng hình, chuyển động mượt trong 0.25 giây */
opacity: 0;
transition: opacity 0.25s ease, background-color 0.2s ease;
}
/* Nút Prev: Bám sát mép trái, chỉ bo tròn 2 góc bên phải */
.slider-btn--prev {
left: 0;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
/* Nút Next: Bám sát mép phải, chỉ bo tròn 2 góc bên trái */
.slider-btn--next {
right: 0;
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
}
/* KHI RÊ CHUỘT VÀO KHUNG BANNER LỚN -> HIỆN CẢ 2 NÚT MŨI TÊN */
.hero-banner-main:hover .slider-btn {
opacity: 1;
}
/* KHI RÊ CHUỘT TRỰC TIẾP VÀO NÚT MŨI TÊN -> NỀN ĐEN ĐẬM LÊN RÕ RỆT */
.slider-btn:hover {
background-color: rgba(0, 0, 0, 0.42);
}
/* --- DÃY CHẤM TRÒN PHÂN TRANG (PAGINATION DOTS) --- */
.slider-dots {
position: absolute;
bottom: 1.2rem; /* Cách đáy Banner 12px */
left: 50%; /* Đưa mép trái của dãy chấm vào giữa Banner */
transform: translateX(-50%); /* Kéo lùi lại 50% chiều rộng của chính dãy chấm để căn tâm ngang tuyệt đối */
display: flex;
align-items: center;
gap: 0.8rem; /* Khoảng cách 8px giữa các chấm tròn */
z-index: var(--z-elevate);
}
.slider-dot {
width: 1rem; /* Đường kính chấm tròn 10px */
height: 1rem;
border-radius: 50%; /* Biến hình vuông thành hình tròn tuyệt đối */
background-color: hsla(0, 0%, 100%, 0.4); /* Màu trắng mờ 40% */
border: 1px solid hsla(0, 0%, 53.7%, 0.4); /* Viền xám mảnh giúp chấm tròn vẫn nhìn rõ nếu gặp ảnh nền màu trắng */
cursor: pointer;
transition: background-color 0.2s ease, border-color 0.2s ease;
}
/* Trạng thái chấm tròn đang được chọn (Active) hoặc khi rê chuột vào */
.slider-dot--active,
.slider-dot:hover {
background-color: var(--shopee-primary); /* Đổi sang màu Cam Shopee #ee4d2d */
border-color: var(--shopee-primary);
}

4. Giải mã dòng code: 4 Tinh hoa UI/UX của các kỹ sư Shopee
-
Nghệ thuật bo góc một phía (
border-top-right-radius):-
Hãy nhìn kỹ hai nút
PrevvàNexttrên Shopee: vì cạnh lưng của nút đã dính chặt vào mép ảnh (left: 0vàright: 0), nếu bạn dùngborder-radius: 4pxcho cả 4 góc, sẽ có một khe hở nhỏ xíu bị lọt sáng ở sát mép tường nhìn rất lỗi! -
Cách làm chuẩn tinh tế: Nút bên trái (
--prev) chỉ bo tròn 2 góc hướng vào trong (top-rightvàbottom-right), giữ 2 góc bên trái vuông góc90 độáp sát vào mép ảnh. Tương tự, nút bên phải (--next) chỉ bo tròn 2 góc bên trái!
-
-
Chiếc viền "cứu mạng" trên chấm tròn (
border: 1px solid hsla(...)):-
Rất nhiều bạn làm chấm tròn phân trang chỉ tô mỗi
background-color: rgba(255, 255, 255, 0.5)(màu trắng mờ). Nhưng trên thực tế, các Designer của nhãn hàng rất hay thiết kế Banner có nền màu trắng tinh ở phần đáy! Khi tấm ảnh nền trắng đi qua, những chấm tròn màu trắng mờ của bạn sẽ tàng hình hoàn toàn! -
Thêm một đường viền xám mảnh
border: 1px solid hsla(0, 0%, 53.7%, 0.4);giúp các chấm tròn luôn hiện rõ ràng dù tấm ảnh quảng cáo bên dưới có màu đen tuyền, cam rực hay trắng xóa.
-
-
Cặp công thức căn tâm kinh điển
translateY(-50%)vàtranslateX(-50%):-
Muốn căn giữa theo chiều dọc cho nút bấm:
top: 50%; transform: translateY(-50%); -
Muốn căn giữa theo chiều ngang cho dãy chấm tròn:
left: 50%; transform: translateX(-50%); -
Bạn không cần biết dãy chấm tròn có 5 chấm, 8 chấm hay 12 chấm (chiều rộng bao nhiêu pixel không quan trọng), trình duyệt luôn tự tính đúng 50% chiều rộng thực tế của thẻ
<ul>để đặt nó ngay chính giữa tấm Banner!
-
-
Thuộc tính hỗ trợ người khiếm thị
aria-label="Ảnh trước":- Vì hai thẻ
<button class="slider-btn">chỉ chứa mỗi thẻ icon<i class="fa-solid fa-chevron-left"></i>mà không có chữ viết bên trong, các công cụ kiểm tra chuẩn SEO (như Google Lighthouse) và trình đọc màn hình sẽ báo lỗi "Buttons do not have an accessible name". Thêmaria-labelgiúp điểm Accessibility của trang web đạt tuyệt đối 100/100!
- Vì hai thẻ
5. Bài tập thực hành cuối bài & Hẹn gặp ở Bài 11!
Hãy lưu lại file index.html và main.css, sau đó quay lại trình duyệt nhấn F5!
-
Khi bạn để chuột ở ngoài, tấm Banner lớn bên trái hiển thị trọn vẹn cùng 6 chấm tròn nhỏ nhắn ở đáy (chấm đầu tiên sáng màu cam Shopee).
-
Ngay khoảnh khắc bạn đưa con trỏ chuột lướt vào tấm Banner lớn, hai nút mũi tên Trái/Phải lập tức hiện dần lên ở hai bên mép. Khi rê chuột thẳng vào nút mũi tên hoặc các chấm tròn, màu sắc phản hồi tức thì cực kỳ chuyên nghiệp!
Thử thách nâng tầm dành cho bạn trước khi sang Bài 11:
-
Hãy thử thêm hiệu ứng biến đổi chấm tròn đang Active thành hình viên thuốc dài (một xu hướng UI rất hot trên Shopee Mall và Tiktok Shop hiện nay): Trong class
.slider-dot--active, bạn hãy thử thêmwidth: 2.4rem; border-radius: 1rem;và thêmtransition: all 0.25s ease;vào.slider-dot. Sau đó thử rê chuột qua từng chấm tròn để xem hiệu ứng chấm tròn giãn dài ra thành viên thuốc màu cam đẹp mắt như thế nào nhé! -
Thử thêm
transform: translateY(-50%) scale(0.9);lúc mặc định vàtransform: translateY(-50%) scale(1);khi:hovercho.slider-btnđể nút bấm vừa hiện rõ vừa hơi nảy nhẹ ra.
Ở Bài 11, chúng ta sẽ hoàn thiện mảnh ghép cuối cùng của khu vực Mặt tiền (.hero-section-wrapper): Xây dựng dãy 8 Icon Dịch Vụ Nổi Bật (Khung Giờ Săn Sale, Miễn Phí Vận Chuyển, Voucher Giảm Đến 1 Triệu, Shopee Mall...) nằm ngay dưới chân cụm Banner với hiệu ứng nhấc nhẹ Icon lên cao (translateY) khi rê chuột vào!
All rights reserved