Ngày xưa, lập trình viên thiết kế trang web cho desktop trước, sau đó “chèn ép” nó vào mobile — kết quả là rất khó sử dụng. Nhưng thời đó đã qua. Hôm nay, hơn 60% lưu lượng web đến từ mobile, nên việc thiết kế cho mobile trước là bắt buộc, không phải tùy chọn.
Mobile First là cách tiếp cận hiện đại: bạn thiết kế và code cho mobile trước, sau đó nâng cấp (enhance) lên tablet/desktop bằng media query. Cách này dễ bảo trì hơn, tối ưu hóa hiệu suất tốt hơn, và đảm bảo trải nghiệm tốt trên tất cả thiết bị.
Mobile First là gì?
Mobile First (hay Progressive Enhancement) là cách tiếp cận lập trình:
- 📱 Bước 1: Viết HTML đơn giản, semantic (cấu trúc tốt)
- 📱 Bước 2: Viết CSS cho mobile (mặc định)
- 💻 Bước 3: Dùng
@media (min-width: ...)để nâng cấp lên tablet/desktop
Lợi ích:
- ✅ Tối ưu hóa mobile (người dùng mobile là đa số)
- ✅ CSS ít hơn (chỉ thêm CSS cần thiết cho desktop)
- ✅ Trang tải nhanh hơn trên mobile
- ✅ Dễ bảo trì (logic rõ ràng)
- ✅ Đảm bảo fallback (hoạt động ngay cả JS bị lỗi)
So sánh: Desktop First vs Mobile First
| Khía cạnh | Desktop First (Cũ) | Mobile First (Mới) ✅ |
|---|---|---|
| Bắt đầu từ | Desktop (1920px) | Mobile (375px) |
| Media query | @media (max-width: 768px) | @media (min-width: 768px) |
| CSS | CSS lớn → phải ẩn/thay đổi trên mobile | CSS nhỏ → thêm feature cho desktop |
| Hiệu suất mobile | Kém (tải CSS không cần) | Tốt (chỉ tải CSS cần thiết) |
| Bảo trì | Phức tạp | Dễ dàng |
/* ❌ DESKTOP FIRST (cũ, không khuyến khích) */
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* 3 cột (desktop) */
gap: 20px;
}
/* Phải viết override cho mobile */
@media (max-width: 768px) {
.container {
grid-template-columns: 1fr 1fr; /* 2 cột (tablet) */
}
}
@media (max-width: 480px) {
.container {
grid-template-columns: 1fr; /* 1 cột (mobile) */
}
}
/* ✅ MOBILE FIRST (mới, khuyến khích) */
.container {
display: grid;
grid-template-columns: 1fr; /* 1 cột (mobile) - mặc định */
gap: 20px;
}
/* Chỉ thêm CSS khi màn hình lớn hơn */
@media (min-width: 481px) {
.container {
grid-template-columns: 1fr 1fr; /* 2 cột (tablet) */
}
}
@media (min-width: 769px) {
.container {
grid-template-columns: 1fr 1fr 1fr; /* 3 cột (desktop) */
}
}Breakpoints tiêu chuẩn (Mobile First)
| Thiết bị | Kích thước | CSS Media Query | Ví dụ |
|---|---|---|---|
| Mobile | 320px – 480px | Mặc định (không cần query) | iPhone, Galaxy A |
| Tablet | 481px – 768px | @media (min-width: 481px) | iPad Mini, Galaxy Tab |
| Desktop nhỏ | 769px – 1024px | @media (min-width: 769px) | Laptop, iPad Pro |
| Desktop lớn | ≥ 1025px | @media (min-width: 1025px) | Desktop, 4K |
Quy trình Mobile First
Bước 1: HTML Semantic (Cấu trúc tốt)
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mobile First Website</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- Header -->
<header class="header">
<h1>My Website</h1>
<nav class="nav">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact</a>
</nav>
</header>
<!-- Main content -->
<main class="container">
<article class="post">
<h2>Article 1</h2>
<p>...</p>
</article>
<article class="post">
<h2>Article 2</h2>
<p>...</p>
</article>
</main>
<!-- Footer -->
<footer class="footer">
<p>© 2024 My Website</p>
</footer>
</body>
</html>Bước 2: CSS cho Mobile (Mặc định)
/* ========== MOBILE FIRST CSS ========== */
/* Base/Reset */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 16px;
}
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f9f9f9;
}
/* Header (mobile) */
.header {
background-color: #2c3e50;
color: white;
padding: 15px;
text-align: center;
}
.header h1 {
font-size: 24px;
margin-bottom: 15px;
}
/* Navigation (mobile - vertical) */
.nav {
display: flex;
flex-direction: column; /* Cột dọc trên mobile */
gap: 10px;
}
.nav a {
display: block;
color: white;
text-decoration: none;
padding: 10px;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 5px;
text-align: center;
}
/* Container (mobile) */
.container {
max-width: 100%;
padding: 15px;
margin: 0 auto;
}
/* Posts (mobile - 1 cột) */
.post {
background: white;
padding: 15px;
margin-bottom: 15px;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.post h2 {
font-size: 18px;
margin-bottom: 10px;
color: #2c3e50;
}
.post p {
font-size: 14px;
color: #666;
}
/* Footer (mobile) */
.footer {
background-color: #2c3e50;
color: white;
text-align: center;
padding: 20px;
font-size: 12px;
}Bước 3: Media Query cho Tablet+ (Min-width)
/* ========== TABLET (481px+) ========== */
@media (min-width: 481px) {
.container {
max-width: 95%;
}
/* Post: 2 cột trên tablet */
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.post {
padding: 20px;
margin-bottom: 0;
}
.post h2 {
font-size: 20px;
}
.post p {
font-size: 15px;
}
}
/* ========== DESKTOP NHỎ (769px+) ========== */
@media (min-width: 769px) {
.header {
padding: 20px 30px;
display: flex;
justify-content: space-between;
align-items: center;
}
.header h1 {
font-size: 32px;
margin-bottom: 0;
}
/* Navigation (desktop - horizontal) */
.nav {
flex-direction: row; /* Ngang trên desktop */
gap: 20px;
}
.nav a {
background-color: transparent;
padding: 8px 15px;
}
.nav a:hover {
background-color: rgba(255, 255, 255, 0.2);
}
/* Container */
.container {
max-width: 1200px;
padding: 40px 20px;
}
/* Post: 3 cột trên desktop */
.container {
grid-template-columns: 1fr 1fr 1fr;
gap: 30px;
}
.post h2 {
font-size: 22px;
}
.post p {
font-size: 16px;
}
}
/* ========== DESKTOP LỚN (1025px+) ========== */
@media (min-width: 1025px) {
.header {
padding: 25px 50px;
}
.header h1 {
font-size: 40px;
}
.container {
max-width: 1400px;
gap: 40px;
}
.post {
padding: 25px;
}
}Ví dụ hoàn chỉnh – Blog responsive Mobile First
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mobile First Blog</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="header">
<h1>📚 Blog</h1>
<button class="menu-toggle">☰ Menu</button>
</header>
<nav class="nav" id="nav">
<a href="#">Trang chủ</a>
<a href="#">Blog</a>
<a href="#">Dịch vụ</a>
<a href="#">Liên hệ</a>
</nav>
<main class="container">
<article class="post">
<img src="post1.jpg" alt="Post 1">
<h2>Bài viết 1: HTML Cơ bản</h2>
<p class="meta">20/12/2024</p>
<p>HTML là nền tảng của web. Học HTML giúp bạn hiểu cấu trúc trang web...</p>
<a href="#" class="btn">Đọc tiếp →</a>
</article>
<article class="post">
<img src="post2.jpg" alt="Post 2">
<h2>Bài viết 2: CSS Cơ bản</h2>
<p class="meta">22/12/2024</p>
<p>CSS dùng để trang trí HTML. Với CSS, bạn có thể tạo những trang web đẹp...</p>
<a href="#" class="btn">Đọc tiếp →</a>
</article>
<article class="post">
<img src="post3.jpg" alt="Post 3">
<h2>Bài viết 3: JavaScript Cơ bản</h2>
<p class="meta">24/12/2024</p>
<p>JavaScript thêm tương tác vào trang web. Học JS để tạo những trang web thực sự sinh động...</p>
<a href="#" class="btn">Đọc tiếp →</a>
</article>
<article class="post">
<img src="post4.jpg" alt="Post 4">
<h2>Bài viết 4: Responsive Design</h2>
<p class="meta">26/12/2024</p>
<p>Responsive design đảm bảo website hoạt động tốt trên mọi thiết bị...</p>
<a href="#" class="btn">Đọc tiếp →</a>
</article>
</main>
<footer class="footer">
<p>© 2024 Blog. Tất cả quyền được bảo lưu.</p>
</footer>
</body>
</html>/* FILE: styles.css - MOBILE FIRST */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 16px;
}
body {
font-family: 'Lato', sans-serif;
line-height: 1.6;
color: #333;
background-color: #f9f9f9;
}
/* ========== HEADER (MOBILE) ========== */
.header {
background-color: #2c3e50;
color: white;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.header h1 {
font-family: 'Playfair Display', serif;
font-size: 28px;
}
.menu-toggle {
background: none;
border: none;
color: white;
font-size: 24px;
cursor: pointer;
display: block; /* Hiển thị trên mobile */
}
/* ========== NAVIGATION (MOBILE) ========== */
.nav {
background-color: #34495e;
display: flex;
flex-direction: column; /* Cột dọc */
gap: 0;
}
.nav a {
color: white;
text-decoration: none;
padding: 15px 20px;
border-bottom: 1px solid #2c3e50;
display: block;
}
.nav a:hover {
background-color: #2c3e50;
}
/* ========== CONTAINER (MOBILE) ========== */
.container {
max-width: 100%;
margin: 0 auto;
padding: 20px;
display: grid;
grid-template-columns: 1fr; /* 1 cột mobile */
gap: 20px;
}
/* ========== POST (MOBILE) ========== */
.post {
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.post img {
width: 100%;
height: 250px;
object-fit: cover;
}
.post h2 {
font-family: 'Playfair Display', serif;
font-size: 20px;
color: #2c3e50;
padding: 15px 15px 0;
margin-bottom: 5px;
}
.post .meta {
padding: 0 15px;
font-size: 12px;
color: #95a5a6;
}
.post p {
padding: 0 15px 15px;
color: #666;
font-size: 14px;
}
.btn {
display: inline-block;
margin: 0 15px 15px;
padding: 10px 20px;
background-color: #3498db;
color: white;
text-decoration: none;
border-radius: 5px;
font-weight: bold;
transition: background-color 0.3s;
}
.btn:hover {
background-color: #2980b9;
}
/* ========== FOOTER (MOBILE) ========== */
.footer {
background-color: #2c3e50;
color: white;
text-align: center;
padding: 20px;
margin-top: 40px;
font-size: 12px;
}
/* ========== TABLET (481px+) ========== */
@media (min-width: 481px) {
.menu-toggle {
display: none; /* Ẩn menu toggle */
}
.nav {
flex-direction: row; /* Ngang */
gap: 0;
background-color: transparent;
}
.nav a {
background-color: #34495e;
border-bottom: none;
border-right: 1px solid #2c3e50;
flex: 1;
text-align: center;
}
.container {
max-width: 95%;
grid-template-columns: 1fr 1fr; /* 2 cột */
gap: 25px;
}
.post img {
height: 200px;
}
.post h2 {
font-size: 18px;
padding: 20px 20px 0;
}
.post .meta {
padding: 5px 20px;
}
.post p {
padding: 10px 20px;
font-size: 15px;
}
.btn {
margin: 0 20px 20px;
}
}
/* ========== DESKTOP NHỎ (769px+) ========== */
@media (min-width: 769px) {
.header {
padding: 25px 40px;
}
.header h1 {
font-size: 36px;
}
.nav {
background-color: #34495e;
}
.nav a {
padding: 15px 25px;
}
.container {
max-width: 1200px;
grid-template-columns: 1fr 1fr 1fr; /* 3 cột */
gap: 30px;
padding: 40px;
}
.post img {
height: 250px;
}
.post h2 {
font-size: 20px;
padding: 20px 20px 0;
}
.post p {
font-size: 16px;
}
.footer {
padding: 30px;
font-size: 14px;
}
}
/* ========== DESKTOP LỚN (1025px+) ========== */
@media (min-width: 1025px) {
.header {
padding: 30px 60px;
}
.header h1 {
font-size: 42px;
}
.nav a {
padding: 15px 35px;
font-size: 16px;
}
.container {
max-width: 1400px;
gap: 40px;
padding: 60px 40px;
}
.post {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.post:hover {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
transform: translateY(-5px);
transition: all 0.3s ease;
}
}Best practices Mobile First
💡 10 Best Practices Mobile First:
- 1. Viewport meta tag: Luôn thêm vào head
- 2. Mobile CSS mặc định: Không cần media query
- 3. Min-width media query: Dùng min-width (> không phải <)
- 4. CSS thứ tự: Mobile → Tablet → Desktop
- 5. Touch-friendly: Button/link ≥ 44px × 44px trên mobile
- 6. Performance: Lazy load images, minimize CSS
- 7. Readable text: Font-size ≥ 16px, line-height 1.5-1.6
- 8. Flexible layout: Dùng %, Flexbox, Grid (không px cứng)
- 9. Test thực tế: Test trên thiết bị thực, không chỉ DevTools
- 10. Progressive enhancement: Cơ bản hoạt động → thêm fancy effect
Checklist Mobile First
Viewport meta tag: ✓
HTML semantic: ✓
Mobile CSS (1 cột): ✓
Tablet CSS (2 cột): ✓
Desktop CSS (3+ cột): ✓
Button/link 44x44px: ✓
Font-size ≥ 16px: ✓
Line-height 1.5-1.6: ✓
Test: mobile, tablet, desktop: ✓Tóm tắt
- ✅ Mobile First: Thiết kế mobile trước, nâng cấp desktop
- ✅ CSS mặc định: Viết CSS cho mobile (không cần query)
- ✅ Min-width media query:
@media (min-width: ...) - ✅ Breakpoints tiêu chuẩn: 480px, 768px, 1024px
- ✅ Viewport meta tag: Bắt buộc cho responsive
- ✅ Flexible layout: %, Flexbox, Grid (không px cứng)
- ✅ Touch-friendly: Button/link ≥ 44px × 44px
- ✅ CSS thứ tự: Mobile → Tablet → Desktop
- ✅ Performance: CSS ít hơn trên mobile
- ✅ Test thực tế: Trên thiết bị thực, không chỉ DevTools
🎯 Bài tập thực hành
Bài tập 1: Chuyển đổi trang web cũ (desktop-first) sang mobile-first:
- Xem trang web hiện tại
- Viết lại CSS với mobile-first approach
- CSS mặc định: 1 cột, font 16px, padding 20px
- Tablet (min-width: 481px): 2 cột, padding 30px
- Desktop (min-width: 769px): 3 cột, padding 40px
- Test trên DevTools: mobile 375px, tablet 768px, desktop 1920px
Bài tập 2: Tạo product catalog responsive mobile-first:
- Mobile: 1 cột sản phẩm, button 44px × 44px
- Tablet: 2 cột, gap 20px
- Desktop: 3 cột, gap 30px, container max-width 1200px
- Mỗi sản phẩm: ảnh responsive, tên, giá, button
- Font-size responsive: h2 18px (mobile) → 22px (desktop)
Bài tập 3: Tạo landing page complete mobile-first:
- Header: logo + hamburger menu (mobile), logo + nav (desktop)
- Hero: full-width image (mobile: 300px, tablet: 400px, desktop: 500px)
- Features: 1 cột → 2 cột → 3 cột
- CTA section: 1 button (mobile) → 2 buttons (desktop)
- Footer: 1 cột → 4 cột
- Touch-friendly: buttons 44px × 44px minimum
Chúc bạn thành công! 🚀