CSS Media Queries: Hướng Dẫn Toàn Diện Từ Cơ Bản Đến Nâng Cao
Làm chủ CSS Media Queries — từ cú pháp cơ bản, breakpoints thông minh, đến các kỹ thuật nâng cao như prefers-color-scheme, prefers-reduced-motion, container queries kết hợp, và responsive typography.
Giới thiệu
CSS Media Queries là một trong những công nghệ nền tảng quan trọng nhất của responsive web design. Từ khi ra mắt trong CSS3, media queries đã thay đổi cách chúng ta xây dựng website — thay vì tạo nhiều phiên bản riêng biệt cho từng thiết bị, giờ đây chúng ta chỉ cần một codebase duy nhất và để CSS tự động điều chỉnh layout dựa trên kích thước màn hình.
Trong bài viết này, chúng ta sẽ đi từ cơ bản đến nâng cao:
- Cú pháp và cách hoạt động của
@media - Các loại media (screen, print, speech…)
- Media features (width, height, orientation, resolution…)
- Chiến lược breakpoints thông minh
- Kỹ thuật nâng cao (dark mode, accessibility, print styles)
- Kết hợp với Container Queries
- Debug và testing
1. Cú Pháp Cơ Bản
Media query có cấu trúc đơn giản:
/* Cú pháp cơ bản */
@media mediatype and (feature: value) {
/* CSS rules */
}
Ví dụ đầu tiên
/* Khi màn hình rộng tối thiểu 768px */
@media screen and (min-width: 768px) {
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
}
Toán tử logic
Media queries hỗ trợ 3 toán tử logic:
| Toán tử | Ý nghĩa | Ví dụ |
|---|---|---|
and | Tất cả điều kiện đều đúng | @media (min-width: 768px) and (orientation: landscape) |
or (,) | Chỉ cần một điều kiện đúng | @media (max-width: 600px), (orientation: portrait) |
not | Phủ định điều kiện | @media not print |
/* AND: cả hai điều kiện */
@media (min-width: 768px) and (max-width: 1024px) {
/* Tablet */
}
/* OR (dùng dấu phẩy): một trong hai */
@media (max-width: 600px), (orientation: portrait) {
/* Mobile hoặc portrait */
}
/* NOT: phủ định */
@media not print {
/* Mọi thứ trừ in ấn */
}
2. Các Loại Media (@media types)
CSS định nghĩa các loại media để áp dụng style cho từng loại thiết bị:
| Media Type | Mục đích |
|---|---|
all | Tất cả thiết bị (mặc định) |
screen | Màn hình máy tính, điện thoại, tablet |
print | Máy in, chế độ Print Preview |
speech | Trình đọc màn hình (screen readers) |
/* Chỉ áp dụng khi in */
@media print {
nav, .sidebar, .ad-banner {
display: none;
}
body {
font-size: 12pt;
color: black;
}
}
/* Chỉ cho trình đọc màn hình */
@media speech {
.footnote {
voice-family: male;
stress: 20;
}
}
Mẹo: Nếu không chỉ định media type, mặc định là
all. Ví dụ@media (min-width: 768px)tương đương với@media all and (min-width: 768px).
3. Media Features (Tính Năng Media)
Media features là các đặc tính của thiết bị mà bạn có thể kiểm tra trong media query.
3.1. Width & Height (Phổ Biến Nhất)
/* Breakpoints phổ biến */
@media (min-width: 640px) { /* Small devices (tablets) */ }
@media (min-width: 768px) { /* Medium devices */ }
@media (min-width: 1024px) { /* Large devices (desktop) */ }
@media (min-width: 1280px) { /* Extra large */ }
@media (min-width: 1536px) { /* 2K and above */ }
min-width vs max-width:
- Mobile-first (khuyên dùng): Dùng
min-width, viết style cho mobile trước, sau đó mở rộng cho màn hình lớn hơn. - Desktop-first: Dùng
max-width, viết cho desktop trước, thu nhỏ dần cho mobile.
/* Mobile-first — khuyên dùng */
/* Mobile styles (mặc định) */
.grid {
display: flex;
flex-direction: column;
}
/* Tablet */
@media (min-width: 768px) {
.grid {
flex-direction: row;
flex-wrap: wrap;
}
.grid-item {
width: 50%;
}
}
/* Desktop */
@media (min-width: 1024px) {
.grid-item {
width: 33.333%;
}
}
3.2. Orientation (Hướng Màn Hình)
/* Landscape (ngang) */
@media (orientation: landscape) {
.hero {
height: 100vh;
}
}
/* Portrait (dọc) */
@media (orientation: portrait) {
.hero {
height: 50vh;
}
}
3.3. Aspect Ratio (Tỷ Lệ Khung Hình)
/* Màn hình vuông hoặc gần vuông (iPad, Surface) */
@media (aspect-ratio: 4/3) {
/* Styles cho 4:3 */
}
/* Màn hình rộng */
@media (min-aspect-ratio: 16/9) {
/* Styles cho widescreen */
}
/* Màn hình siêu rộng (ultrawide) */
@media (min-aspect-ratio: 21/9) {
.container {
max-width: 1400px;
}
}
3.4. Resolution (Độ Phân Giải)
/* Retina / HiDPI screens */
@media (min-resolution: 2dppx) {
.logo {
background-image: url('logo@2x.png');
}
}
@media (min-resolution: 3dppx) {
.logo {
background-image: url('logo@3x.png');
}
}
/* Các đơn vị resolution: dpi (dots per inch), dpcm (dots per cm), dppx (dots per pixel) */
3.5. Display Mode (PWA)
/* Khi chạy dưới dạng PWA fullscreen */
@media (display-mode: standalone) {
body {
padding-top: env(safe-area-inset-top);
}
}
@media (display-mode: fullscreen) {
.header {
display: none;
}
}
4. Chiến Lược Breakpoints Thông Minh
4.1. Breakpoints Theo Nội Dung (Content-First)
Thay vì dùng breakpoints theo thiết bị phổ biến (320px, 768px, 1024px…), hãy để nội dung quyết định breakpoint:
/* Content-first approach */
/* Khi 2 cột không còn đủ chỗ, chuyển về 1 cột */
@media (max-width: 700px) {
.two-column-layout {
grid-template-columns: 1fr;
}
}
/* Khi 3 cột quá chật, chuyển về 2 cột */
@media (max-width: 900px) {
.three-column-layout {
grid-template-columns: 1fr 1fr;
}
}
4.2. Breakpoints Tham Khảo
/* Cascade từ nhỏ đến lớn (mobile-first) */
/* Base: mobile (< 640px) */
/* Mặc định không cần media query */
/* sm: tablet nhỏ (≥ 640px) */
@media (min-width: 640px) {}
/* md: tablet lớn (≥ 768px) */
@media (min-width: 768px) {}
/* lg: desktop (≥ 1024px) */
@media (min-width: 1024px) {}
/* xl: desktop lớn (≥ 1280px) */
@media (min-width: 1280px) {}
/* 2xl: màn hình rộng (≥ 1536px) */
@media (min-width: 1536px) {}
4.3. Range Syntax (Cú Pháp Khoảng CSS Mới)
CSS Media Queries Level 4 giới thiệu cú pháp khoảng mới, ngắn gọn hơn:
/* Cách cũ */
@media (min-width: 768px) and (max-width: 1024px) {}
/* Cách mới — dễ đọc hơn */
@media (768px <= width <= 1024px) {}
/* Lớn hơn hoặc bằng 768px */
@media (width >= 768px) {}
/* Nhỏ hơn hoặc bằng 1024px */
@media (width <= 1024px) {}
Lưu ý: Cú pháp range được hỗ trợ trên tất cả trình duyệt hiện đại (Chrome, Firefox, Safari 16.4+, Edge). Nếu cần hỗ trợ trình duyệt cũ, hãy dùng
min-width/max-width.
5. Kỹ Thuật Nâng Cao
5.1. Dark Mode (prefers-color-scheme)
:root {
--bg: #ffffff;
--text: #1a1a1a;
--primary: #2563eb;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #0f172a;
--text: #e2e8f0;
--primary: #60a5fa;
}
}
body {
background-color: var(--bg);
color: var(--text);
}
5.2. Giảm Chuyển Động (prefers-reduced-motion)
Tôn trọng nhu cầu của người dùng nhạy cảm với chuyển động:
/* Mặc định: có animation */
@keyframes slideIn {
from { transform: translateX(100px); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.animated-element {
animation: slideIn 0.5s ease;
}
/* Người dùng yêu cầu giảm chuyển động */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
.animated-element {
animation: none;
opacity: 1; /* Hiển thị ngay lập tức */
}
}
5.3. Tương Phản Cao (prefers-contrast)
@media (prefers-contrast: high) {
:root {
--text: #000000;
--bg: #ffffff;
--border: 2px solid black;
}
.card {
border: 2px solid currentColor;
box-shadow: none;
}
}
@media (prefers-contrast: less) {
:root {
--text: #555;
--bg: #fafafa;
}
}
5.4. Responsive Typography
/* Typography thích ứng */
h1 {
font-size: clamp(1.75rem, 4vw + 1rem, 3.5rem);
line-height: 1.2;
}
@media (min-width: 768px) {
h1 {
letter-spacing: -0.02em;
}
}
@media (min-width: 1024px) {
h1 {
max-width: 80%;
}
}
/* Responsive spacing */
:root {
--section-padding: clamp(2rem, 5vw, 6rem);
--container-padding: clamp(1rem, 3vw, 2rem);
}
5.5. Print Stylesheet
@media print {
/* Ẩn elements không cần thiết */
nav, .sidebar, .footer, .ads,
button, video, .comments {
display: none !important;
}
/* Reset màu sắc */
* {
background: transparent !important;
color: black !important;
box-shadow: none !important;
text-shadow: none !important;
}
/* Typography cho in ấn */
body {
font-size: 12pt;
line-height: 1.5;
}
h1 { font-size: 24pt; }
h2 { font-size: 18pt; }
h3 { font-size: 14pt; }
/* Links hiển thị URL */
a[href^="http"]::after {
content: " (" attr(href) ")";
font-size: 0.8em;
color: #555 !important;
}
/* Page breaks */
h2, h3 { page-break-after: avoid; }
.section { page-break-inside: avoid; }
@page {
margin: 2cm;
}
}
6. Kết Hợp Media Queries với Container Queries
CSS Container Queries (ra mắt năm 2023) cho phép component phản hồi dựa trên kích thước container thay vì viewport. Kết hợp cả hai:
/* Container query — dựa trên kích thước container */
.card-container {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}
@container card (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
}
}
/* Media query — dựa trên viewport, dùng cho layout tổng thể */
@media (min-width: 1024px) {
.dashboard {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
Khi nào dùng Media Query, khi nào dùng Container Query?
- Media Query: Layout toàn trang, sidebar/main structure, global typography
- Container Query: Component-level responsive, reusable UI components
7. Custom Media Queries (PostCSS Custom Media)
Nếu dùng PostCSS, bạn có thể định nghĩa custom media queries để tái sử dụng:
/* Định nghĩa */
@custom-media --mobile (max-width: 639px);
@custom-media --tablet (min-width: 640px) and (max-width: 1023px);
@custom-media --desktop (min-width: 1024px);
@custom-media --dark (prefers-color-scheme: dark);
@custom-media --motion-ok (prefers-reduced-motion: no-preference);
/* Sử dụng */
@media (--desktop) {
.layout { display: grid; }
}
@media (--dark) {
:root { --bg: #1a1a2e; }
}
8. Debug Media Queries
8.1. Hiển Thị Breakpoint Hiện Tại
/* Thêm vào CSS để debug */
body::after {
content: "Mobile";
position: fixed;
bottom: 10px;
right: 10px;
background: red;
color: white;
padding: 4px 12px;
border-radius: 4px;
font-family: monospace;
font-size: 14px;
z-index: 9999;
}
@media (min-width: 640px) {
body::after { content: "sm (≥640px)"; background: orange; }
}
@media (min-width: 768px) {
body::after { content: "md (≥768px)"; background: green; }
}
@media (min-width: 1024px) {
body::after { content: "lg (≥1024px)"; background: blue; }
}
@media (min-width: 1280px) {
body::after { content: "xl (≥1280px)"; background: purple; }
}
8.2. Testing Tools
| Tool | Công dụng |
|---|---|
| Chrome DevTools Device Toolbar | Mô phỏng nhiều thiết bị |
| Firefox Responsive Design Mode | Tương tự Chrome |
resize event trong JS | Test real-time |
| LambdaTest / BrowserStack | Test trên thiết bị thật |
9. Best Practices
✅ DO
- Mobile-first: Luôn viết style cơ bản cho mobile trước, dùng
min-widthđể mở rộng - Content-first breakpoints: Để nội dung quyết định breakpoint, không chạy theo thiết bị
- Dùng CSS custom properties: Kết hợp media queries với variables để dễ bảo trì
- Test trên thiết bị thật: Không chỉ dựa vào DevTools
- Giới hạn số breakpoints: 3-4 breakpoints là đủ cho đa số dự án
❌ DON’T
- Không dùng media queries cho mọi thứ: CSS Grid/Flexbox đã tự động responsive tốt
- Không hardcode breakpoints: Dùng variables hoặc design tokens
- Không quên print styles: Website của bạn có thể được in ra
- Không lạm dụng
!important: Cascade của media queries đã đủ mạnh
Ví dụ Hoàn Chỉnh
/* Variables */
:root {
--gap: 1rem;
--columns: 1;
--container-max: 100%;
}
/* Mobile-first grid */
.grid {
display: grid;
grid-template-columns: repeat(var(--columns), 1fr);
gap: var(--gap);
max-width: var(--container-max);
margin: 0 auto;
padding: 0 var(--gap);
}
/* Tablet */
@media (min-width: 640px) {
:root {
--columns: 2;
--gap: 1.5rem;
--container-max: 600px;
}
}
/* Desktop */
@media (min-width: 1024px) {
:root {
--columns: 3;
--gap: 2rem;
--container-max: 960px;
}
}
/* Large desktop */
@media (min-width: 1280px) {
:root {
--columns: 4;
--container-max: 1200px;
}
}
10. Tương Lai: Media Queries Level 5
CSS Media Queries Level 5 đang được phát triển với nhiều tính năng mới:
/* prefers-reduced-data — giảm tải dữ liệu */
@media (prefers-reduced-data: reduce) {
.hero-video {
display: none;
}
.hero-image {
display: block;
}
}
/* prefers-color-scheme: light | dark | no-preference */
/* forced-colors: active | none */
/* inverted-colors: inverted | none */
/* scripting: enabled | none (kiểm tra JavaScript có bật không) */
Kết Luận
CSS Media Queries là công cụ không thể thiếu trong toolkit của bất kỳ web developer nào. Từ responsive layout cơ bản đến accessibility, dark mode, và print styles, media queries giúp bạn tạo ra những website hoạt động tốt trên mọi thiết bị và hoàn cảnh.
3 điều cần nhớ:
- Mobile-first: Luôn bắt đầu từ màn hình nhỏ nhất
- Content-first: Breakpoints dựa trên nội dung, không phải thiết bị
- Accessibility: Tận dụng
prefers-reduced-motionvàprefers-contrastđể phục vụ tất cả người dùng
Với những kiến thức trong bài này, bạn đã sẵn sàng để xây dựng những website responsive chuyên nghiệp, thân thiện với mọi người dùng và thiết bị.
Bạn có câu hỏi về CSS Media Queries? Hãy để lại comment bên dưới — đội ngũ Devs2.org luôn sẵn sàng giúp đỡ!