Giao diện phải đẹp trên điện thoại, máy tính bảng và màn hình lớn. Bài này dạy tư duy mobile-first, viết media query theo breakpoint, container query để thành phần tự thích ứng theo khung chứa, và các media feature như chế độ tối, giảm chuyển động.
- Áp dụng mobile-first với min-width
- Chọn breakpoint hợp lý
- Dùng container query cho thành phần
- Dùng prefers-color-scheme, prefers-reduced-motion, hover
- Breakpoint
- Mốc chiều rộng đổi bố cục.
- Mobile-first
- Viết CSS cho màn hình nhỏ trước, mở rộng dần.
- Container query
- Điều kiện theo kích thước phần tử chứa thay vì màn hình.
Một số khái niệm
Điều kiện tiên quyết: thẻ <meta name="viewport" content="width=device-width, initial-scale=1">. Sau đó, viết CSS mặc định cho điện thoại (bố cục 1 cột), rồi dùng @media (min-width: ...) thêm cột khi màn hình rộng hơn. Cách này giữ CSS cho điện thoại nhẹ và đơn giản.
| Breakpoint gợi ý | Thiết bị |
|---|---|
| < 576px | Điện thoại dọc (mặc định) |
| ≥ 576px | Điện thoại ngang |
| ≥ 768px | Máy tính bảng |
| ≥ 992px | Laptop |
| ≥ 1200px | Màn hình lớn |
Đừng chọn breakpoint theo từng thiết bị cụ thể; hãy thu nhỏ trình duyệt và thêm breakpoint ở chỗ giao diện bắt đầu vỡ.
Media query mobile-first
<style>
.ds { display: grid; gap: 8px; grid-template-columns: 1fr; }
.ds div { background: #e3f2fd; padding: 14px; border-radius: 8px; text-align: center; }
@media (min-width: 420px) { .ds { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 640px) { .ds { grid-template-columns: repeat(4, 1fr); } .ds div { background: #e8f5e9; } }
@media (orientation: landscape) and (max-height: 400px) { .ds div { padding: 6px; } }
</style>
<div class="ds"><div>1</div><div>2</div><div>3</div><div>4</div></div>
<p style="font-size:13px;color:#666">Thu nhỏ cửa sổ trình duyệt: 4 → 2 → 1 cột.</p>/* Cú pháp khoảng (range syntax) mới, dễ đọc */
@media (480px <= width < 992px) { ... }Container query
<style>
.vo { container-type: inline-size; border: 2px dashed #90a4ae; padding: 8px; margin-bottom: 8px; border-radius: 8px; }
.the { display: grid; gap: 10px; background: #fff; }
.the .anh { aspect-ratio: 16/9; background: #90a4ae; border-radius: 6px; }
@container (min-width: 380px) { .the { grid-template-columns: 140px 1fr; } .the .anh { aspect-ratio: 1; } }
</style>
<div class="vo" style="width:300px"><div class="the"><div class="anh"></div><div><b>Thẻ trong cột hẹp</b><br>Ảnh nằm trên</div></div></div>
<div class="vo"><div class="the"><div class="anh"></div><div><b>Thẻ trong cột rộng</b><br>Ảnh tự chuyển sang trái</div></div></div>Cùng một thẻ, đặt vào cột hẹp (sidebar) hay cột rộng (nội dung chính) tự đổi bố cục theo khung chứa, không phụ thuộc màn hình. Đây là cách xây thành phần tái sử dụng hiện đại.
Media feature về người dùng
/* Chế độ tối theo hệ điều hành */
@media (prefers-color-scheme: dark) {
:root { --nen: #121212; --chu: #e0e0e0; }
}
/* Người dùng bật giảm chuyển động */
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}
/* Chỉ áp dụng hiệu ứng hover cho thiết bị có chuột */
@media (hover: hover) and (pointer: fine) {
.the:hover { transform: translateY(-4px); }
}
/* Khi in */
@media print { nav, footer, .quang-cao { display: none; } a::after { content: " (" attr(href) ")"; } }Ảnh responsive: img { max-width: 100%; height: auto; } và dùng thuộc tính srcset, sizes để trình duyệt tải ảnh vừa kích thước màn hình (xem HTML - Hình ảnh).
Kiểm thử trên điện thoại thật, không chỉ chế độ thiết bị của DevTools: font, thanh địa chỉ, vùng chạm ngón tay (tối thiểu 44×44px) khác biệt đáng kể.
- Chuyển một trang 3 cột sang mobile-first: 1 → 2 → 3 cột.
- Làm thanh menu: điện thoại hiện nút ☰, máy tính hiện đủ mục.
- Tạo thẻ sản phẩm dùng container query.
- Thêm chế độ tối theo prefers-color-scheme bằng biến CSS.
- viewport + mobile-first + min-width.
- Breakpoint theo nơi giao diện vỡ.
- @container cho thành phần tự thích ứng.
- prefers-color-scheme, prefers-reduced-motion, hover, print.