Responsive: เว็บเดียวใช้ได้ทุกจอ
viewport meta, media queries, breakpoints และ mobile-first mindset ทำให้เว็บที่เขียนในคอม ใช้บนมือถือได้โดยไม่พัง
เขียนเว็บในคอมแล้วสวยงาม ปุ่มใหญ่ๆ 3 คอลัมน์ ข้อความเห็นชัด พอเปิดมือถือเข้ามาดูครั้งแรกเห็นนรกเปล่าๆ ตัวอักษรเล็กจิ๋ว layout ซ้อนกันเละ ต้อง zoom in ถึงจะอ่านได้
นี่คือปัญหาที่ทุกคนทำเว็บครั้งแรกต้องเจอ เพราะส่วนใหญ่เขียนในคอม ลืมว่า 60% ของคนเข้าเว็บใช้มือถือ บทนี้จะทำให้เว็บเดียวของเราใช้งานได้ดีทั้งบนมือถือและบนคอม
3 ชิ้นที่ต้องมีสำหรับ responsive
Responsive web คือเว็บที่ปรับตัวตามขนาดจอ ทำได้โดยใช้ 3 ชิ้นประกอบกัน:
- viewport meta tag บอก browser ให้ใช้ขนาดจอจริง ไม่ zoom out
- media queries CSS ที่เปลี่ยนตามขนาดจอ
- flexible units ใช้ %, rem, vw แทน px ตายตัว
viewport meta tag สิ่งแรกที่ต้องมี
ใส่ไว้ใน <head> ของทุกหน้า:
<meta name="viewport" content="width=device-width, initial-scale=1">ถ้าไม่ใส่ มือถือจะเห็นเว็บคุณเหมือนเว็บ desktop ย่อเล็ก user ต้อง pinch zoom ถึงจะอ่านได้ ปัจจุบัน template ทุกตัว (Next.js, React, Vue) ใส่ให้แล้ว แต่ถ้าทำ HTML เปล่าต้องใส่เองทุกครั้ง
อ่านความหมายได้ดังนี้:
width=device-widthคือ viewport กว้างเท่าจอจริง (ไม่ใช่ 980px default)initial-scale=1คือเปิดครั้งแรก zoom 100% (ไม่ย่อเล็ก)
media queries CSS เปลี่ยนตามจอ
@media คือกฎพิเศษใน CSS ที่บอกว่า "ถ้าจอตรงเงื่อนไขนี้ ให้ใช้ rule ข้างใน"
/* mobile default */
.cards { grid-template-columns: 1fr; }
/* tablet ขึ้นไป จอกว้างขึ้น กลายเป็น 2 คอลัมน์ */
@media (min-width: 640px) {
.cards { grid-template-columns: 1fr 1fr; }
}
/* desktop กลายเป็น 3 คอลัมน์ */
@media (min-width: 1024px) {
.cards { grid-template-columns: 1fr 1fr 1fr; }
}ลองลาก viewport slider ดูว่า layout ปรับตัวตามจำนวนคอลัมน์ที่แต่ละช่วงจอ:
Breakpoints ที่ใช้จริง
"Breakpoint" คือจุดที่ layout เปลี่ยน ทุก framework มี breakpoint ชุดของตัวเอง แต่ส่วนใหญ่ใช้ 4 ตัวนี้เป็นหลัก:
- 640px สำหรับมือถือใหญ่หรือ tablet เล็ก
- 768px สำหรับ tablet แนวตั้ง
- 1024px สำหรับ tablet แนวนอนหรือ laptop เล็ก
- 1280px สำหรับ desktop
ไม่มีเลขศักดิ์สิทธิ์ ขึ้นกับว่าเว็บของคุณเริ่ม layout พังตรงขนาดไหน ลากดูเลย Tailwind ใช้ 640/768/1024/1280/1536 ถ้าไม่รู้จะเลือกอะไรใช้ของ Tailwind ก็ได้
Mobile-first กับ Desktop-first
เวลาเขียน responsive มี 2 แนวคิด ผลลัพธ์เหมือนกัน แต่ clarity ต่างกันมาก:
/* เริ่มที่ desktop styles */
.cards {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 24px;
}
/* ต้อง override เป็น mobile ที่หน้าจอเล็กลง */
@media (max-width: 1023px) {
.cards {
grid-template-columns: 1fr 1fr;
gap: 16px;
}
}
@media (max-width: 639px) {
.cards {
grid-template-columns: 1fr;
gap: 12px;
}
}- ต้อง override ค่าที่ตั้งไปแล้ว CSS รกขึ้นเรื่อยๆ
- max-width คิดย้อนทิศ อ่านแล้วงงว่าเกิดอะไรตอนไหน
- มือถือโหลดก่อน แต่อ่าน CSS ของ desktop ก่อน = เสีย performance
/* เริ่มที่ mobile styles ตัว default */
.cards {
display: grid;
grid-template-columns: 1fr;
gap: 12px;
}
/* ขยาย feature ขึ้นเรื่อยๆ ตามขนาดจอ */
@media (min-width: 640px) {
.cards {
grid-template-columns: 1fr 1fr;
gap: 16px;
}
}
@media (min-width: 1024px) {
.cards {
grid-template-columns: 1fr 1fr 1fr;
gap: 24px;
}
}- เพิ่ม feature ทีละชั้น CSS อ่านเรียงลงมาเข้าใจ flow ได้เลย
- มือถือโหลด default CSS ก่อน ไม่ต้องอ่าน override = เร็วกว่า
- min-width คิดเป็นลำดับจาก 640 ไป 1024 ขยายใหญ่ขึ้น ไม่ต้อง reverse
min-width เป็นหลัก ไม่ใช้ max-width ยกเว้นกรณีจำเป็นจริงๆ (เช่น hide element ที่แสดงเฉพาะ desktop)Flexible units อย่าใช้ px ตายตัว
Responsive ไม่ใช่แค่เรื่อง media queries units ที่ใช้ก็ต้องยืดหยุ่นด้วย
%คือ % ของ parent เช่นwidth: 50%คือครึ่งหนึ่งของ parentremคืออัตราส่วนของ font root (default 16px) ใช้กับ font-size และ spacingvw / vhคือ % ของ viewport width หรือ height เช่น100vhคือเต็มจอแนวตั้งchคือกว้าง "0" ในฟอนต์ปัจจุบัน เหมาะกับ max-width ของข้อความ (ประมาณ65chคือ 65 ตัวอักษรต่อบรรทัด)min() / max() / clamp()คือ CSS function ที่เลือกค่าอัตโนมัติตามบริบท
Pattern ที่ใช้ทุกวัน
1. Stack บน mobile เปลี่ยนเป็น row บน desktop
.layout {
display: flex;
flex-direction: column; /* mobile: stack */
gap: 16px;
}
@media (min-width: 768px) {
.layout {
flex-direction: row; /* tablet+: row */
}
}2. Grid ปรับคอลัมน์ตามจอ
.cards {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 640px) { .cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .cards { grid-template-columns: repeat(3, 1fr); } }3. Hide element บน mobile
.desktop-only {
display: none;
}
@media (min-width: 1024px) {
.desktop-only { display: block; }
}สรุป
- ใส่
<meta name="viewport">ทุกหน้า ไม่งั้นมือถือจะเห็นเว็บย่อเล็ก - Media queries คือ CSS ที่เปลี่ยนตามจอ ใช้
@media (min-width: Xpx)เป็นหลัก - Breakpoints พื้นฐานคือ 640 / 768 / 1024 / 1280 ปรับตามที่ layout เริ่มพัง
- Mobile-first เริ่มที่มือถือ เพิ่ม feature ตามจอใหญ่ขึ้น อ่านสบายและ performance ดีกว่า
- Units ยืดหยุ่นมี % / rem / vw / vh / ch ใช้
clamp()ช่วย responsive font-size ใน 1 บรรทัด - Test ด้วย DevTools responsive mode ร่วมกับเครื่องจริง
บทถัดไปคือ Capstone เอาทุกอย่างที่เรียนใน topic นี้มารวมกับ JS จาก stage 1 สร้าง interactive feature จริง คือปุ่ม toggle theme ที่กดแล้วหน้าเปลี่ยน นี่คือครั้งแรกที่ JS ของคุณออกจาก console มาแก้ DOM จริงๆ