Skip to main content
CSS 5 mins read Devs2.org

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.

#CSS #Media Queries #Responsive Design #Breakpoints #Frontend #Web Development

CSS Media Queries Complete Guide

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:

  1. Cú pháp và cách hoạt động của @media
  2. Các loại media (screen, print, speech…)
  3. Media features (width, height, orientation, resolution…)
  4. Chiến lược breakpoints thông minh
  5. Kỹ thuật nâng cao (dark mode, accessibility, print styles)
  6. Kết hợp với Container Queries
  7. 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ĩaVí dụ
andTấ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)
notPhủ đị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 TypeMục đích
allTất cả thiết bị (mặc định)
screenMàn hình máy tính, điện thoại, tablet
printMáy in, chế độ Print Preview
speechTrì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

ToolCông dụng
Chrome DevTools Device ToolbarMô phỏng nhiều thiết bị
Firefox Responsive Design ModeTương tự Chrome
resize event trong JSTest real-time
LambdaTest / BrowserStackTest trên thiết bị thật

9. Best Practices

✅ DO

  1. Mobile-first: Luôn viết style cơ bản cho mobile trước, dùng min-width để mở rộng
  2. Content-first breakpoints: Để nội dung quyết định breakpoint, không chạy theo thiết bị
  3. Dùng CSS custom properties: Kết hợp media queries với variables để dễ bảo trì
  4. Test trên thiết bị thật: Không chỉ dựa vào DevTools
  5. Giới hạn số breakpoints: 3-4 breakpoints là đủ cho đa số dự án

❌ DON’T

  1. Không dùng media queries cho mọi thứ: CSS Grid/Flexbox đã tự động responsive tốt
  2. Không hardcode breakpoints: Dùng variables hoặc design tokens
  3. Không quên print styles: Website của bạn có thể được in ra
  4. 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ớ:

  1. Mobile-first: Luôn bắt đầu từ màn hình nhỏ nhất
  2. Content-first: Breakpoints dựa trên nội dung, không phải thiết bị
  3. Accessibility: Tận dụng prefers-reduced-motionprefers-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 đỡ!

Recently Used Tools