Responsive Web Design
Responsive Web Design RWD Media Queries Flexbox CSS Grid Mobile First Viewport Breakpoint Container Queries Testing Production SEO Performance
| Technique | Use Case | Browser Support | Complexity | เหมาะกับ |
|---|---|---|---|---|
| Media Queries | Layout breakpoints | ทุก Browser | ง่าย | Page-level responsive |
| Flexbox | 1D layout (row/col) | ทุก Browser | ง่าย | Nav, cards, centering |
| CSS Grid | 2D layout | ทุก Browser | ปานกลาง | Complex page layouts |
| Container Queries | Component-level | Modern browsers | ปานกลาง | Reusable components |
| Clamp() | Fluid typography | Modern browsers | ง่าย | Responsive font sizes |
| Viewport Units | Full-screen sections | ทุก Browser | ง่าย | Hero sections, spacing |
CSS Implementation
/* === Responsive CSS — Mobile First === */
/* Base styles — Mobile (320px+) */
/* :root {
--max-width: 1200px;
--gap: 1rem;
--font-base: clamp(0.875rem, 0.8rem + 0.5vw, 1.125rem);
}
body {
font-size: var(--font-base);
line-height: 1.6;
padding: 0 var(--gap);
}
.container {
max-width: var(--max-width);
margin: 0 auto;
padding: 0 var(--gap);
}
/* Card Grid — Mobile: 1 col, Tablet: 2 col, Desktop: 3 col */
/* .card-grid {
display: grid;
gap: var(--gap);
grid-template-columns: 1fr;
}
/* Tablet (768px+) */
/* @media (min-width: 48em) {
.card-grid {
grid-template-columns: repeat(2, 1fr);
}
.sidebar-layout {
display: grid;
grid-template-columns: 250px 1fr;
gap: 2rem;
}
}
/* Desktop (1024px+) */
/* @media (min-width: 64em) {
.card-grid {
grid-template-columns: repeat(3, 1fr);
}
}
/* Fluid Typography */
/* h1 { font-size: clamp(1.5rem, 1.2rem + 2vw, 3rem); }
h2 { font-size: clamp(1.25rem, 1rem + 1.5vw, 2.25rem); }
p { font-size: clamp(0.875rem, 0.8rem + 0.5vw, 1.125rem); }
/* Responsive Images */
/* img {
max-width: 100%;
height: auto;
display: block;
}
/* Container Queries */
/* .card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 150px 1fr;
}
} */
from dataclasses import dataclass
@dataclass
class Breakpoint:
name: str
min_width: str
em_value: str
columns: int
target: str
breakpoints = [
Breakpoint("Mobile S", "320px", "20em", 1, "iPhone SE, small phones"),
Breakpoint("Mobile L", "480px", "30em", 1, "Standard phones"),
Breakpoint("Tablet", "768px", "48em", 2, "iPad, tablets"),
Breakpoint("Laptop", "1024px", "64em", 3, "Small laptops"),
Breakpoint("Desktop", "1200px", "75em", 4, "Standard desktop"),
Breakpoint("Wide", "1440px", "90em", 4, "Wide monitors"),
]
print("=== Breakpoints ===")
for b in breakpoints:
print(f" [{b.name}] min-width: {b.min_width} ({b.em_value})")
print(f" Columns: {b.columns} | Target: {b.target}")
Flexbox and Grid Patterns
# === Common Responsive Patterns ===
# /* Navigation — Hamburger on Mobile, Horizontal on Desktop */
# .nav {
# display: flex;
# flex-direction: column;
# }
# .nav-toggle { display: block; } /* Hamburger button */
# .nav-links { display: none; }
# .nav-links.active { display: flex; flex-direction: column; }
#
# @media (min-width: 48em) {
# .nav { flex-direction: row; align-items: center; }
# .nav-toggle { display: none; }
# .nav-links { display: flex; flex-direction: row; gap: 1rem; }
# }
#
# /* Holy Grail Layout */
# .page {
# display: grid;
# min-height: 100vh;
# grid-template-rows: auto 1fr auto;
# grid-template-columns: 1fr;
# }
# @media (min-width: 48em) {
# .page {
# grid-template-columns: 200px 1fr 200px;
# grid-template-rows: auto 1fr auto;
# }
# header, footer { grid-column: 1 / -1; }
# }
#
# /* Responsive Table */
# @media (max-width: 48em) {
# table, thead, tbody, th, td, tr {
# display: block;
# }
# td::before {
# content: attr(data-label);
# font-weight: bold;
# }
# }
@dataclass
class ResponsivePattern:
pattern: str
technique: str
mobile: str
desktop: str
css: str
patterns = [
ResponsivePattern("Navigation", "Flexbox", "Hamburger menu, vertical", "Horizontal links",
"flex-direction: column → row"),
ResponsivePattern("Card Grid", "CSS Grid", "1 column stack", "3-4 column grid",
"grid-template-columns: 1fr → repeat(3, 1fr)"),
ResponsivePattern("Sidebar", "CSS Grid", "Stacked (content first)", "Side + main layout",
"1fr → 250px 1fr"),
ResponsivePattern("Hero Section", "Flexbox + vh", "Full width, smaller text", "Full viewport hero",
"min-height: 50vh → 100vh"),
ResponsivePattern("Table", "Display block", "Card-like rows", "Standard table",
"display: table → block"),
ResponsivePattern("Typography", "Clamp()", "Smaller fluid text", "Larger fluid text",
"clamp(1rem, 0.8rem + 1vw, 2rem)"),
]
print("\n=== Responsive Patterns ===")
for p in patterns:
print(f" [{p.pattern}] Tech: {p.technique}")
print(f" Mobile: {p.mobile}")
print(f" Desktop: {p.desktop}")
print(f" CSS: {p.css}")
Testing and Performance
# === Responsive Testing Checklist ===
@dataclass
class TestItem:
category: str
check: str
tool: str
pass_criteria: str
checks = [
TestItem("Viewport", "Meta viewport tag present", "View source",
''),
TestItem("Images", "No horizontal scroll from images", "DevTools resize",
"img { max-width: 100%; height: auto; }"),
TestItem("Touch", "Buttons min 44x44px", "DevTools measure",
"All interactive elements >= 44px tap target"),
TestItem("Font", "Readable without zoom (>=16px)", "DevTools inspect",
"Body font-size >= 16px on mobile"),
TestItem("Layout", "No content overflow/hidden", "Resize all breakpoints",
"No horizontal scroll, no cut content"),
TestItem("Speed", "Mobile Lighthouse >= 90", "Lighthouse audit",
"Performance score >= 90 on mobile"),
TestItem("SEO", "Mobile-friendly test pass", "Google Search Console",
"No mobile usability errors"),
TestItem("Orientation", "Works in landscape + portrait", "DevTools rotate",
"Layout adapts to both orientations"),
]
print("Responsive Testing Checklist:")
for c in checks:
print(f" [{c.category}] {c.check}")
print(f" Tool: {c.tool}")
print(f" Pass: {c.pass_criteria}")
perf_tips = {
"Responsive Images": "Use srcset + sizes for different resolutions",
"Lazy Loading": 'loading="lazy" on below-fold images',
"CSS containment": "contain: layout style for isolated components",
"Print styles": "@media print { } for printable pages",
"Prefers": "@media (prefers-color-scheme: dark) for dark mode",
"Reduced motion": "@media (prefers-reduced-motion: reduce) for accessibility",
}
print(f"\n\nPerformance Tips:")
for k, v in perf_tips.items():
print(f" [{k}]: {v}")
เคล็ดลับ
- Mobile First: เขียน CSS สำหรับมือถือก่อน ใช้ min-width เพิ่ม
- em: ใช้ em แทน px สำหรับ Media Query Scale ตาม Font Size
- Clamp: ใช้ clamp() สำหรับ Fluid Typography ไม่ต้อง Media Query
- Container: ใช้ Container Queries สำหรับ Component-level Responsive
- Test: ทดสอบบนมือถือจริง ไม่พึ่ง DevTools อย่างเดียว
Responsive Web Design คืออะไร
แสดงผลดีทุกขนาดจอ มือถือ แท็บเล็ต Desktop Media Queries Flexible Grid Image Viewport Flexbox Grid Container Queries
Mobile First คืออะไร
ออกแบบมือถือก่อน min-width เพิ่ม Style จอใหญ่ CSS น้อย เร็ว Content สำคัญก่อน Google Mobile-first Indexing SEO Desktop First ตรงข้าม
Breakpoint ตั้งอย่างไร
ตาม Content ไม่ใช่ Device 320 480 768 1024 1200 1440 em แทน px Scale Font Size Container Queries Component-level
ทดสอบ Responsive อย่างไร
Chrome DevTools Device Mode มือถือจริง BrowserStack Touch Events Viewport Meta Image Font Button 44px Landscape Portrait Lighthouse Mobile
สรุป
Responsive Web Design Media Queries Flexbox CSS Grid Mobile First Breakpoint Container Queries Clamp Viewport Testing Lighthouse SEO Performance Production
