[Series 100 Bài Học HTML/CSS Thực Chiến - Bài 25]: Khởi Động Chương 9 — Làm Chủ Responsive Web Design Với @media queries, Thiết Lập Hệ Thống Breakpoints & Biến Hóa Header Shopee Trên Tablet / Mobile!
Chào mừng anh em đã chạm tới cột mốc lịch sử: Bài 25 — Hoàn thành chặng đường trong chuỗi 100 Bài Học Làm Chủ HTML/CSS Qua Dự Án Clone Shopee!
Trải qua 24 bài học đầu tiên, chúng ta đã dựng nên một đế chế giao diện Shopee Desktop (1200px) đồ sộ từ Trang chủ, Popup Đăng nhập, Trang Tìm kiếm, Chi tiết sản phẩm cho đến Giỏ hàng và Thanh toán. Tuy nhiên, có một sự thật trong ngành Thương mại điện tử mà mọi kỹ sư Frontend đều phải biết: Hơn 80% lưu lượng truy cập mua sắm trên Shopee hiện nay đến từ Điện thoại di động (Mobile) và Máy tính bảng (Tablet)!
Nếu bạn mở công cụ Chrome DevTools (F12), bật chế độ giả lập điện thoại (Toggle Device Toolbar - Ctrl + Shift + M) và chọn màn hình iPhone 14 Pro Max (430px) hay iPad Mini (768px), bạn sẽ thấy giao diện Desktop hiện tại của chúng ta gặp ngay 3 vấn đề nghiêm trọng:
-
Thanh Top Navbar chứa quá nhiều chữ (Kênh Người Bán, Trở thành Người bán, Tải ứng dụng, Thông báo...) bị ép chặt vào nhau, gãy thành 3–4 dòng đè lên thanh Tìm kiếm bên dưới!
-
Khung Logo Shopee (
200px) và Giỏ hàng (150px) chiếm mất350pxchiều ngang, khiến thanh Tìm kiếm ở giữa trên màn hình điện thoại (375px) bị bóp nghẹt chỉ còn rộng vỏn vẹn25px— không thể gõ chữ! -
Dãy từ khóa gợi ý bên dưới thanh Search và thanh Sắp xếp sản phẩm bị tràn ra ngoài mép phải màn hình, xuất hiện thanh cuộn ngang (
Horizontal Scrollbar) rất khó chịu.
Trong Bài 25 hôm nay — bài mở màn cho Chương 9: Responsive Web Design, chúng ta sẽ học cách thiết lập hệ thống Media Queries (@media) chuẩn mực, đồng thời "phẫu thuật thẩm mỹ" cho toàn bộ vùng Header Shopee để nó tự động thu gọn thành giao diện Mobile App gọn gàng, kèm theo Thanh lọc nhanh trượt ngang (Mobile Sort Bar) đặc trưng trên điện thoại!
1. Bản chất của Responsive Web Design & Hệ thống 3 Điểm Gãy (Breakpoints) chuẩn E-Commerce
Responsive Web Design (Thiết kế web đáp ứng) là kỹ thuật dùng CSS Media Queries (@media) để phát hiện kích thước chiều rộng màn hình của thiết bị đang xem, từ đó tự động thay đổi bố cục (ẩn bớt thành phần rườm rà, giảm số cột từ 6 xuống 4 hoặc 2 cột) sao cho vừa vặn nhất với mắt người dùng.
Hãy nhìn vào sơ đồ minh họa cách một giao diện web tự động co giãn và sắp xếp lại các khối nội dung từ màn hình Desktop sang Laptop, Tablet và Phone dưới đây:

Vì dự án của chúng ta đang đi theo hướng Desktop-First (xây dựng bản PC đầy đủ trước rồi thu gọn dần xuống màn hình nhỏ), chúng ta sẽ sử dụng thuộc tính max-width (áp dụng CSS khi chiều rộng màn hình nhỏ hơn hoặc bằng một con số nhất định) với 3 quy tắc vàng:
Plaintext
0px 739px 1023px 1200px+
|---------------------------|-------------------------|-------------------------|
📱 MOBILE (Điện thoại) 📟 TABLET (iPad/Tab) 💻 PC / DESKTOP LỚN
(max-width: 739px) (740px -> 1023px) (min-width: 1024px)
|___________________________|_________________________|
▲
Gộp chung: MOBILE & TABLET (max-width: 1023px)
1. Cú pháp @media chung cho cả Mobile & Tablet (Dưới 1024px)
Cú pháp: @media (max-width: 1023px)
- Ẩn hoàn toàn thanh Top Navbar (34px) và dãy từ khóa Hot Trend bên dưới thanh Search.
- Thu gọn chiều cao tổng của Header từ 120px xuống chỉ còn 68px.
- Ẩn danh sách sản phẩm trong Giỏ hàng mini khi hover (vì màn hình cảm ứng không có chuột để hover).
- Bật Thanh Sắp xếp Mobile (Mobile Sort Bar) bám ngay dưới đáy Header.
2. Riêng cho Tablet (iPad) (Từ 740px đến 1023px)
Cú pháp: @media (min-width: 740px) and (max-width: 1023px)
- Thu hẹp khung
.grid-containerxuống 644px hoặc 100% có padding 16px. - Khung Giỏ hàng thu gọn về 80px sát mép phải.
3. Riêng cho Mobile (Điện thoại) (Dưới 740px)
Cú pháp: @media (max-width: 739px)
- Ẩn khung Logo lớn bên trái (hoặc đưa vào giữa), nhường 100% không gian cho Thanh Tìm Kiếm và Icon Giỏ Hàng.
- Bật nút Icon Tìm kiếm / Menu Mobile ở góc trái.
Tại sao lại có quy tắc gộp
@media (max-width: 1023px)?Nếu bạn viết riêng một cục code ẩn
.top-navbartrong Tablet, rồi lại copy-paste chính cục code đó xuống Mobile, file CSS của bạn sẽ bị lặp code gấp đôi! Đặt những điểm chung của cả hai thiết bị cảm ứng (Tablet + Mobile) vào@media (max-width: 1023px)giúp bạn chỉ cần viết 1 lần mà chạy trên cả iPad lẫn iPhone!
2. Giải phẫu Header Shopee trên Điện thoại: Tối giản để Tối ưu!
Trên màn hình điện thoại nhỏ hẹp (375px – 430px), người dùng điều khiển bằng ngón tay cái (Thumb Zone) chứ không phải con trỏ chuột chính xác 1px. Do đó, Shopee thực hiện cuộc "đại phẫu" Header như sau:
-
Biến hình từ 2 tầng (
120px) thành 1 tầng duy nhất (68px):Toàn bộ chữ Kênh Người Bán, Tải ứng dụng, Thông báo trên
.top-navbarvà dãy từ khóa gợi ý.header-search-suggest-listđược ẩn đi bằngdisplay: none;. -
Bổ sung Thanh Sắp Xếp Mobile (
header__sort-bar) bám dính dưới đáy Header:Trên PC, thanh Sắp xếp (Phổ biến | Mới nhất | Bán chạy | Giá) nằm mãi trong cột 10 phần của trang Danh mục. Nhưng trên Mobile & Tablet, Shopee gắn luôn một thanh 4 tab Phổ biến | Mới nhất | Bán chạy | Giá cao
46pxnằm ngay sát dưới đáy Header cam để người dùng lướt bằng 1 ngón tay cực tiện!
3. Thực hành: Tạo File responsive.css & Biến Hóa Header Shopee Đa Thiết Bị
Để code không bị lẫn lộn với gần 1.000 dòng CSS Desktop trong main.css, chúng ta sẽ tạo một file riêng biệt mang tên ./assets/css/responsive.css và nhúng nó ở dòng cuối cùng trong thẻ <head> (để nó có quyền ghi đè lên các thuộc tính của main.css).
Bước 1: Nhúng responsive.css và bổ sung header__sort-bar vào index.html
- Mở file
index.html, tìm đến thẻ<head>ở đầu trang và thêm dòng<link>tới fileresponsive.cssngay dướimain.css:
HTML
<!-- 3. Các file CSS nội bộ của dự án (responsive.css luôn nằm cuối cùng!) -->
<link rel="stylesheet" href="./assets/css/reset.css">
<link rel="stylesheet" href="./assets/css/base.css">
<link rel="stylesheet" href="./assets/css/main.css">
<link rel="stylesheet" href="./assets/css/responsive.css">
</head>
- Tiếp theo, vẫn trong
index.html, tìm đến thẻ<header class="shopee-header">. Ngay bên dưới thẻ đóng</div>của.header-with-search(trước khi đóng</header>), bạn hãy bổ sung thêm Thanh Sắp Xếp Mobile (.header-sort-bar) (Mặc định trên PC thanh này sẽ ẩn đi, chỉ tự động hiện ra khi màn hình nhỏ hơn1024px!):
HTML
<!-- Khu vực Logo, Tìm kiếm và Giỏ hàng -->
<div class="header-with-search">
<!-- Nút Menu / Tìm kiếm nhanh chỉ hiện trên Mobile (< 740px) -->
<label for="mobile-search-checkbox" class="header-mobile-search">
<i class="header-mobile-search-icon fa-solid fa-bars"></i>
</label>
<!-- (Giữ nguyên .header-logo, .header-search-wrapper, .header-cart bên trong) -->
...
</div>
</div>
<!-- THANH LỌC NHANH DÀNH RIÊNG CHO MOBILE & TABLET (Mặc định ẩn trên PC) -->
<ul class="header-sort-bar">
<li class="header-sort-item">
<a href="#" class="header-sort-link">Liên quan</a>
</li>
<li class="header-sort-item header-sort-item--active">
<a href="#" class="header-sort-link">Mới nhất</a>
</li>
<li class="header-sort-item">
<a href="#" class="header-sort-link">Bán chạy</a>
</li>
<li class="header-sort-item">
<a href="#" class="header-sort-link">
Giá <i class="fa-solid fa-sort" style="margin-left: 4px; font-size: 1.2rem;"></i>
</a>
</li>
</ul>
</header>
Bước 2: Viết CSS mặc định cho .header-sort-bar trong ./assets/css/main.css
Trước khi viết Media Queries, hãy mở cuối file main.css và thêm đoạn CSS định hình cho thanh .header-sort-bar cùng nút .header-mobile-search (mặc định đặt display: none trên Desktop):
CSS
/* Bổ sung vào cuối file ./assets/css/main.css */
/* --- CHƯƠNG 9 (BÀI 25): CÁC COMPONENT HỖ TRỢ MOBILE / TABLET HEADER --- */
/* Nút Menu góc trái trên Mobile (Mặc định ẩn trên PC & Tablet) */
.header-mobile-search {
padding: 0 1.2rem;
display: none;
cursor: pointer;
}
.header-mobile-search-icon {
font-size: 2.4rem;
color: var(--white-color);
}
/* Thanh Sắp Xếp Mobile & Tablet bám dưới đáy Header (Mặc định ẩn trên PC) */
.header-sort-bar {
position: fixed;
top: var(--header-height);
left: 0;
right: 0;
height: 4.6rem; /* Cao 46px chuẩn Mobile App */
background-color: var(--white-color);
border-top: 1px solid #e5e5e5;
border-bottom: 1px solid #e5e5e5;
display: none; /* Ẩn trên màn hình PC lớn */
z-index: calc(var(--z-sticky) - 1);
}
.header-sort-item {
flex: 1; /* Chia đều 4 tab mỗi tab rộng đúng 25% màn hình! */
}
.header-sort-link {
color: var(--text-primary);
font-size: 1.4rem;
display: block;
height: 100%;
line-height: 4.6rem;
text-align: center;
position: relative;
}
/* Vẽ vạch ngăn cách dọc giữa 4 tab bằng ::before */
.header-sort-link::before {
content: "";
position: absolute;
top: 50%;
left: 0;
height: 60%;
border-left: 1px solid #e5e5e5;
transform: translateY(-50%);
}
/* Xóa vạch ngăn cách ở tab đầu tiên bên trái */
.header-sort-item:first-child .header-sort-link::before {
display: none;
}
/* Trạng thái Tab đang chọn (Active): Chữ cam + Gạch chân cam dày 2px ở đáy */
.header-sort-item--active .header-sort-link {
color: var(--shopee-primary);
border-bottom: 2px solid var(--shopee-primary);
font-weight: 500;
}
Bước 3: Tạo file ./assets/css/responsive.css và thiết lập 3 Breakpoints chuẩn mực!
Bây giờ, hãy tạo một file mới tên là responsive.css nằm trong thư mục ./assets/css/ và gõ đoạn code Responsive đầu tiên của dự án:
CSS
/* ./assets/css/responsive.css */
/* ================================================================= */
/* 1. MOBILE & TABLET CHUNG (Màn hình nhỏ hơn hoặc bằng 1023px) */
/* ================================================================= */
@media (max-width: 1023px) {
/* Thu gọn chiều cao biến Header từ 120px xuống 68px! */
:root {
--header-height: 6.8rem;
--navbar-height: 0px;
}
/* Thêm khoảng đệm 2 bên mép màn hình để chữ không dính sát viền điện thoại/iPad */
.grid-container {
padding-left: 1.2rem;
padding-right: 1.2rem;
}
/* Ẩn các thành phần chỉ dành cho PC: Top Navbar, Từ khóa Hot Trend & Thanh Sort Bar PC */
.top-navbar,
.header-search-suggest-list,
.home-filter {
display: none;
}
/* Cố định Header và đẩy phần thân trang xuống bù lại 68px (Header) + 46px (Sort bar) */
.shopee-header {
position: fixed;
top: 0;
left: 0;
right: 0;
}
.shopee-body {
margin-top: calc(var(--header-height) + 4.6rem); /* 68px + 46px = 114px */
}
.header-search-wrapper {
margin-top: 0; /* Xóa margin-top 12px của bản PC để căn chính giữa 68px */
}
/* Bật Thanh Sắp Xếp 4 cột dành cho Mobile & Tablet */
.header-sort-bar {
display: flex;
}
/* Chuyển hộp Giỏ hàng mini sang tràn ngang toàn màn hình dưới đáy Header */
.header-cart-list {
position: fixed;
top: var(--header-height);
right: 0;
left: 0;
width: 100%;
padding: 0 calc((100% - 64.4rem) / 2);
}
/* Ẩn mũi tên tam giác của Giỏ hàng khi ở dạng Full-width trên Mobile/Tablet */
.header-cart-list::before {
display: none;
}
}
/* ================================================================= */
/* 2. RIÊNG CHO TABLET / IPAD (Từ 740px đến 1023px) */
/* ================================================================= */
@media (min-width: 740px) and (max-width: 1023px) {
.header-with-search {
padding: 0;
}
/* Thu gọn khung Logo và Giỏ hàng trên iPad để nhường chỗ cho thanh Tìm kiếm */
.header-logo {
width: 14rem;
}
.header-logo-svg {
width: 12rem;
}
.header-cart {
width: 7rem;
justify-content: flex-end;
}
}
/* ================================================================= */
/* 3. RIÊNG CHO MOBILE / ĐIỆN THOẠI (Nhỏ hơn hoặc bằng 739px) */
/* ================================================================= */
@media (max-width: 739px) {
.header-with-search {
justify-content: space-between;
padding: 0 0.4rem;
gap: 0.8rem;
}
/* Hiện nút Icon Menu góc trái trên Điện thoại */
.header-mobile-search {
display: block;
}
/* Ẩn bớt khối Logo lớn 200px để Thanh Tìm Kiếm bung rộng trên màn hình hẹp 375px! */
.header-logo {
display: none;
}
/* Thu gọn kích thước nút kính lúp và ô input cho vừa ngón tay trên Mobile */
.header-search {
height: 3.6rem;
}
.header-search-input {
padding: 0 0.8rem;
font-size: 1.3rem;
}
.header-search-btn {
width: 4.8rem;
height: 3rem;
}
/* Lịch sử tìm kiếm bung rộng 100% chiều ngang màn hình điện thoại */
.header-search-history {
position: fixed;
top: var(--header-height);
left: 0;
width: 100%;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
}
.header-cart {
width: auto;
padding: 0 0.8rem;
}
}

4. Giải mã dòng code: 3 Tuyệt kỹ Responsive "nhỏ mà có võ" trong Bài 25
-
Ghi đè Biến CSS (
:root) bên trong@media (max-width: 1023px):-
Đây là khoảnh khắc bạn thấy quyết định dùng biến
--header-heightvà hàmcalc()từ Bài 02 phát huy tác dụng kỳ diệu như thế nào! -
Trên PC,
--header-heightlà120pxvà--navbar-heightlà34px. Khi vào@media (max-width: 1023px), chúng ta chỉ cần khai báo lại:--header-height: 6.8rem; --navbar-height: 0px; -
Ngay lập tức, biến
--header-with-search-height: calc(var(--header-height) - var(--navbar-height))tự động tính lại thành68px - 0px = 68px! Toàn bộ thanh.header-sort-barvà hộp.header-cart-list(vốn dùngtop: var(--header-height)) cũng tự động dịch chuyển lên mốc68pxmà không phải đi sửa từng dòngtop: 120px!
-
-
Đổi hộp Lịch sử tìm kiếm & Giỏ hàng từ
position: absolutesangposition: fixedtrên Mobile:-
Trên PC (
1200px), hộp Giỏ hàng rộng400pxnằmposition: absolutengay dưới icon xe đẩy. -
Nhưng trên màn hình điện thoại iPhone SE (
320px) hay iPhone 13 (375px), một chiếc hộp cứng400pxsẽ đâm thủng mép trái màn hình! Bằng cách đổi sangposition: fixed; top: var(--header-height); left: 0; right: 0; width: 100%;, hộp Giỏ hàng và Lịch sử tìm kiếm lập tức biến thành một ngăn kéo trải rộng vừa khít 100% màn hình điện thoại!
-
-
Thủ thuật vẽ vạch ngăn cách chiều cao 60% (
height: 60%) trên.header-sort-link::before:- Thay vì cố định chiều cao vạch ngăn cách bằng
pxnhư ở Bài 03, trên thanh.header-sort-bar(46px), chúng ta đặtheight: 60%; top: 50%; transform: translateY(-50%);. Dù sau này chiều cao thanh Sort Bar thay đổi, vạch kẻ dọc vẫn luôn bằng đúng 60% chiều cao của thanh và căn giữa hoàn hảo!
- Thay vì cố định chiều cao vạch ngăn cách bằng
5. Bài tập trải nghiệm "Kéo thả màn hình" & Hẹn gặp ở Bài 26!
Hãy lưu lại toàn bộ các file (index.html, main.css, responsive.css), mở trình duyệt lên và nhấn F12 (hoặc Ctrl + Shift + M) để bật chế độ Responsive!
-
Hãy thử nắm cạnh phải của màn hình trình duyệt và kéo thu nhỏ từ từ từ
1200pxxuống dưới mốc1023px(Chế độ iPad / Tablet):-
Lập tức thanh Top Navbar và dãy từ khóa gợi ý biến mất!
-
Thanh Header thu gọn về
68px, bên dưới xuất hiện ngay thanh 4 tab Liên quan | Mới nhất | Bán chạy | Giá sắc nét!
-
-
Tiếp tục kéo nhỏ xuống dưới mốc
739px(Chế độ Điện thoại iPhone375px):- Khối Logo lớn tự động ẩn đi, nhường chỗ cho nút Menu 3 gạch (
☰) ở góc trái, thanh Tìm kiếm ở giữa bung rộng thoải mái và icon Giỏ hàng có số3nằm gọn ở góc phải — y hệt giao diện Mobile Web của Shopee thật!
- Khối Logo lớn tự động ẩn đi, nhường chỗ cho nút Menu 3 gạch (
Thử thách khám phá dành cho bạn trước khi sang Bài 26:
-
Hãy thử bấm chuột vào ô tìm kiếm khi đang ở màn hình Mobile (
375px) để xem hộp Lịch sử tìm kiếm giờ đây xổ xuống tràn đều 100% chiều ngang màn hình điện thoại đẹp mắt như thế nào! -
Bạn có nhớ kỹ thuật Checkbox Hack ở Bài 16 không? Hãy thử tạo một
<input type="checkbox" id="mobile-search-checkbox">để khi bấm vào nút Icon góc trái (.header-mobile-search), một thanh Menu trượt từ mép trái màn hình ra (Mobile Drawer Sidebar) sẽ xuất hiện nhé!
Ở Bài 26, chúng ta sẽ tiếp tục cuộc "đại phẫu Responsive" xuống phần thân trang: Tối ưu Cụm Hero Banner, Thanh 8 Icon Dịch Vụ trượt ngang bằng ngón tay (overflow-x: auto + scroll-snap-type) và Lưới Sản Phẩm tự động co từ 6 Cột (PC) 4 Cột (Tablet) 2 Cột (Mobile)!
4 -> 2 cột) ngay chứ?" query="Hãy giúp tôi soạn tiếp Bài 26 trong series: Tối ưu Responsive cho phần Thân trang Shopee trên Tablet & Mobile (Hero Banner, Vuốt ngang danh mục bằng CSS Scroll Snap và Lưới sản phẩm 6 -> 4 -> 2 cột)."/>
All rights reserved