CSS
Grid
grid vs flex use cases
Flex จัดวางแบบ 1 มิติ เหมาะกับแถวเดียว / Grid จัดวางแบบ 2 มิติ เหมาะกับตาราง — บทเรียนนี้สอนให้เลือกใช้ได้ถูกต้องในทุกสถานการณ์
หัวข้อนี้คืออะไร
Flex และ Grid คือสองระบบ layout หลักของ CSS ที่ใช้จัดวาง element บนหน้าเว็บ แต่ทั้งสองเหมาะกับงานคนละประเภท Flex คือ layout แบบ 1 มิติ — จัดวาง element ในแนวแถวหรือแนวคอลัมน์ทีละทิศทาง เช่น navigation bar, button group, หรือ card row Grid คือ layout แบบ 2 มิติ — จัดวาง element ในทั้งแถวและคอลัมน์พร้อมกัน เช่น card grid, photo gallery, หรือ page layout เลือกผิดไม่ใช่แค่ทำให้โค้ดยาวขึ้น แต่ทำให้ responsive ยาก layout ไม่เสถียร และแก้ bug ได้ยาก
- Flex = 1 มิติ — จัดวางแนวเดียว (แถว หรือ คอลัมน์)
- Grid = 2 มิติ — จัดวางทั้งแถวและคอลัมน์พร้อมกัน
- ทั้งสองใช้ร่วมกันได้ — ไม่ต้องเลือกอย่างเดียวทั้งหน้า
- เลือกตามธรรมชาติของ layout ไม่ใช่ตามความถนัดส่วนตัว
ทำไมหัวข้อนี้สำคัญ
ถ้าเลือกใช้ผิด จะเกิดปัญหาชัดเจน 3 อย่าง: ใช้ Grid กับ layout แนวเดียว เช่น navbar — ต้องเขียน grid-template-columns เพิ่มเติม ทั้งที่ Flex จัดการได้ทันทีด้วยบรรทัดเดียว โค้ดยาวกว่าที่ควรโดยไม่จำเป็น ฝืนใช้ Flex กับ layout หลายแถวหลายคอลัมน์ — ต้องใช้ flex-wrap บวกกับ width: calc(33% - ...) แบบ manual ทำให้ layout เปราะ responsive ยุ่ง และแก้ยากมากเมื่อจำนวน item เปลี่ยน เลือกผิดแล้วแก้ทีหลัง — มักกระทบ CSS ทั้งก้อน เพราะ Flex กับ Grid ใช้ property คนละชุด การสลับระบบกลางคัน = refactor ยาว
ตัวอย่างจากชีวิตจริง
ลองนึกถึงการจัดห้องอาหารในร้าน ถ้าคุณแค่ต้องการเก้าอี้เรียงต่อกันตามแนวผนัง — นั่นคืองานแนวเดียว ใช้แค่ระยะห่างระหว่างเก้าอี้ก็พอ เหมือน Flex ที่เน้นการจัดเรียงในทิศทางเดียว แต่ถ้าต้องจัดโต๊ะให้เต็มห้องเป็นตาราง กำหนดว่าแถวไหนห่างเท่าไร คอลัมน์ไหนกว้างเท่าไร — นั่นคืองาน 2 มิติ ต้องวางแผนทั้งแนวนอนและแนวตั้งพร้อมกัน เหมือน Grid ที่ควบคุมโครงสร้างทั้งหมดจาก parent เมื่อมีห้องจริง ร้านอาหารใช้ทั้งสอง: Grid สำหรับโซนโต๊ะทั้งห้อง Flex สำหรับจัดจานบนแต่ละโต๊ะ
แนวคิดหลักที่ต้องเข้าใจ
กฎง่าย ๆ ที่ใช้ตัดสินใจ: Flex — เหมาะเมื่อ layout มีทิศทางเดียว items เรียงต่อกันในแนวนอนหรือแนวตั้ง ระยะห่างระหว่าง items คือสิ่งสำคัญ ไม่ต้องกำหนดโครงสร้างแถว/คอลัมน์ล่วงหน้า → navbar, button group, tag list, card row, icon + label Grid — เหมาะเมื่อ layout มีสองทิศทาง ต้องการกำหนดทั้งแถวและคอลัมน์ items ต้องอยู่ในช่องที่กำหนด parent ควบคุมโครงสร้างทั้งหมด → card grid, photo gallery, dashboard, page layout (header/sidebar/main/footer) ใช้ร่วมกัน — ทำได้เสมอ ใช้ Grid สำหรับ layout ระดับบน แล้วใช้ Flex ภายใน component ย่อยได้พร้อมกัน ทั้งสองไม่ขัดกัน
การทำงานทีละขั้นตอน
ใช้คำถาม 3 ข้อนี้เพื่อตัดสินใจว่าควรใช้อะไร:
- 1. layout นี้มีกี่ทิศทาง? — ถ้าแนวเดียว (แถวหรือคอลัมน์) → Flex / ถ้าสองทิศทาง (แถวและคอลัมน์) → Grid
- 2. parent ต้องควบคุม layout ทั้งหมดไหม? — ถ้า parent กำหนดโครงสร้าง → Grid / ถ้าแค่จัดระยะห่างระหว่าง items → Flex
- 3. จำนวน items เปลี่ยนได้ไหม? — ถ้าเพิ่ม/ลบ item แล้ว layout ต้องปรับอัตโนมัติโดยไม่แก้ CSS → Flex มักง่ายกว่า / ถ้าต้องการโครงสร้างคงที่ → Grid
- ถ้ายังไม่แน่ใจ — ถามว่า 'component นี้คล้าย navbar มากกว่าหรือคล้าย card grid มากกว่า?' แล้วเลือกตามนั้น
- ไม่มีคำตอบ 'ผิดเสมอ' — บาง layout ใช้ได้ทั้งสอง แต่มักมีตัวที่ 'เหมาะกว่า' อยู่เสมอ
ตัวอย่างเชิงเทคนิค / โค้ด
ตัวอย่างที่ 1 — Flex เหมาะกว่า: Navigation Bar Navbar คือ layout แนวเดียว link เรียงต่อกันแนวนอน Flex จัดการได้ทันทีด้วย gap และ align-items ไม่ต้องกำหนด columns
ตัวอย่างเชิงเทคนิค / โค้ด — Grid
ตัวอย่างที่ 2 — Grid เหมาะกว่า: Card Layout Card grid ต้องการโครงสร้าง 2 มิติ card ทุกใบกว้างเท่ากัน เรียงเป็นแถวและคอลัมน์ Grid จัดการได้ในบรรทัดเดียว
ตัวอย่างเชิงเทคนิค / โค้ด — ใช้ร่วมกัน
ตัวอย่างที่ 3 — ใช้ร่วมกัน: Page Layout + Card Footer ไม่ต้องเลือกอย่างเดียว Grid ควบคุม page layout ระดับบน Flex จัดการ component ย่อยข้างใน
จุดที่ผู้เริ่มต้นมักสับสน
- ❌ ใช้ Grid กับ layout แนวเดียว เช่น navbar หรือ tag list → ✅ ใช้ Flex แทน เพราะไม่มีโครงสร้าง 2 มิติ Grid จึงฝืนธรรมชาติและทำโค้ดยาวโดยไม่จำเป็น
- ❌ ฝืนใช้ Flex กับ card grid โดยใช้ flex-wrap + width: calc(33% - ...) → ✅ ใช้ Grid แทน เพราะ grid-template-columns จัดการได้ตรงกว่าและไม่ต้องคำนวณ width manual
- ❌ คิดว่า Grid ดีกว่า Flex เสมอเพราะทำได้มากกว่า → ✅ เลือกตามธรรมชาติของ layout ไม่ใช่ความสามารถ: 1 มิติ = Flex, 2 มิติ = Grid
- ❌ คิดว่าต้องเลือกใช้แค่อย่างเดียวทั้งหน้า → ✅ ใช้ Grid สำหรับ layout ระดับบน และ Flex สำหรับ component ย่อยข้างในได้พร้อมกัน ทั้งสองไม่ขัดกัน
เปรียบเทียบกับสิ่งที่ใกล้เคียง
เปรียบเทียบสถานการณ์ใช้งานจริงของ Flex และ Grid:
| สถานการณ์ | ใช้ Flex | ใช้ Grid | เหตุผล |
|---|---|---|---|
| Navigation bar | ✅ เหมาะกว่า | ได้ แต่ฝืน | link เรียงแนวเดียว ไม่มีโครงสร้าง 2 มิติ |
| Card grid (3 คอลัมน์) | ได้ แต่ฝืน | ✅ เหมาะกว่า | ต้องควบคุมทั้งแถวและคอลัมน์พร้อมกัน |
| Button group / Tag list | ✅ เหมาะกว่า | ได้ แต่ฝืน | items เรียงแนวเดียว จำนวนไม่ตายตัว |
| Page layout (header/sidebar/main) | ได้ แต่ยาก | ✅ เหมาะกว่า | ต้องกำหนดโครงสร้างหน้าทั้งหมด |
| Photo gallery | ได้ แต่ฝืน | ✅ เหมาะกว่า | รูปทุกใบต้องกว้าง/สูงเท่ากัน เรียงเป็นตาราง |
| Card footer (icon + label + button) | ✅ เหมาะกว่า | ได้ แต่ฝืน | elements เรียงแนวเดียว justify ระหว่างกัน |
สรุปท้ายบทแบบจำง่าย
ถ้าจัด layout เป็นแนวเดียว ให้ใช้ Flex / ถ้าต้องคุมทั้งแถวและคอลัมน์ ให้ใช้ Grid ถ้า component เป็น row หรือ column เดียว ให้ใช้ Flex / ถ้าเป็นพื้นที่แบบตารางหรือ page layout ให้ใช้ Grid
- Flex = 1 มิติ → navbar, tag list, button group, card footer
- Grid = 2 มิติ → card grid, gallery, dashboard, page layout
- ใช้ร่วมกันได้ — Grid ระดับบน, Flex ระดับล่าง
- ถ้าไม่แน่ใจ ถามว่า 'ต้องควบคุมทั้งแถวและคอลัมน์ไหม?' ตอบ ใช่ = Grid / ไม่ใช่ = Flex
Lab 1: จัด Navbar ด้วย Flex
โจทย์: เพิ่ม display: flex ให้ .navbar เพื่อให้ link ทั้ง 4 ตัวเรียงในแนวนอน
Lab 2: สร้าง Card Grid 3 คอลัมน์
โจทย์: เพิ่ม display: grid และ grid-template-columns: repeat(3, 1fr) ให้ .card-grid เพื่อสร้าง layout 3 คอลัมน์
Lab 3: แก้ Layout ให้ถูกประเภท
โจทย์: แก้ .tag-group จากที่ใช้ Grid อยู่ให้เปลี่ยนมาใช้ Flex แทน เพราะ tag list เป็น layout 1 มิติ ไม่ใช่ 2 มิติ