CSS Flexbox vs Grid: คุณควรใช้ระบบ Layout ไหน?
ทั้ง Flexbox และ CSS Grid สามารถสร้างผลลัพธ์ที่คล้ายกันได้ นั่นคือเหตุผลที่นักพัฒนามักเลือกผิดในบางครั้ง ความแตกต่างอยู่ที่มิติเดียวเทียบกับสองมิติ — และการรู้ว่าคุณกำลังรับมือกับอะไรจะทำให้การตัดสินใจเลือกชัดเจนยิ่งขึ้น
กฎแบบประโยคเดียว (The One-Sentence Rule)
ใช้ Flexbox เมื่อคุณกำลังจัดวางไอเทมใน ทิศทางเดียว (แถวหรือคอลัมน์) ใช้ CSS Grid เมื่อคุณต้องการควบคุมเลย์เอาต์ใน สองทิศทางพร้อมกัน (ทั้งแถวและคอลัมน์พร้อมกัน)
นั่นคือใจความสำคัญทั้งหมด ส่วนอื่น ๆ คือการขยายความว่าทำไมกฎนั้นถึงใช้งานได้จริง
สิ่งที่ Flexbox ทำได้ดีจริงๆ
Flexbox ถูกออกแบบมาเพื่อ การกระจายพื้นที่ตามแกนเดียว ฟีเจอร์เด่นของมันคือไอเทมสามารถขยาย ย่อ และตัดบรรทัดได้อย่างเป็นธรรมชาติโดยที่คุณไม่ต้องระบุขนาดที่แน่นอนสำหรับแต่ละชิ้น
นี่คือกรณีที่ Flexbox เป็นตัวเลือกที่เหมาะสม:
- แถบนำทาง (Navigation bars) — แถวของลิงก์ที่คุณต้องการให้บางไอเทมถูกดันไปทางขวา (
margin-left: auto) หรือเว้นระยะห่างเท่า ๆ กัน (justify-content: space-between) - แถวการ์ด (Card rows) ที่แต่ละการ์ดมีความสูงเท่ากันโดยไม่คำนึงถึงความยาวของเนื้อหา (
align-items: stretchจัดการเรื่องนี้ให้โดยอัตโนมัติ) - การจัดตำแหน่งองค์ประกอบให้อยู่กึ่งกลาง (Centering an element) ทั้งในแนวนอนและแนวตั้งภายในคอนเทนเนอร์ — ใช้ CSS สามบรรทัด:
display: flex; justify-content: center; align-items: center - กลุ่มปุ่ม (Button groups), การผสมผสานระหว่างไอคอน + ป้ายกำกับ และส่วนประกอบใด ๆ ที่ต้องการให้ลูก ๆ วางเรียงข้างกันโดยมีระยะห่างบางอย่าง
- รายการแบบตัดบรรทัด (Wrapping lists) ที่คุณต้องการให้ไอเทมตัดลงไปบรรทัดถัดไปเมื่อไม่มีพื้นที่เหลือ (
flex-wrap: wrap)
.navbar {
display: flex;
align-items: center;
gap: 1rem;
}
.navbar .logo { margin-right: auto; }
/* logo อยู่ซ้าย, links อยู่ขวา */
สิ่งที่ CSS Grid ทำได้ดีจริงๆ
Grid ถูกออกแบบมาสำหรับ เลย์เอาต์แบบสองมิติ — คุณกำหนดทั้งแถวและคอลัมน์ และสามารถวางไอเทมลงในเซลล์ได้อย่างแม่นยำ ข้ามหลายแถวหรือคอลัมน์ และสร้างช่องว่างในทั้งสองทิศทาง
นี่คือกรณีที่ Grid เป็นตัวเลือกที่เหมาะสม:
- เลย์เอาต์หน้าเว็บ (Page layouts) — header, sidebar, main content, footer ทั้งหมดถูกวางตำแหน่งสัมพันธ์กัน
- เลย์เอาต์นิตยสารหรือแดชบอร์ด (Magazine or dashboard layouts) ที่ไอเทมต่าง ๆ ใช้พื้นที่ไม่เท่ากัน
- แกลเลอรีรูปภาพ (Image galleries) ที่มีโครงสร้างกริดที่สม่ำเสมอโดยไม่คำนึงถึงขนาดของรูปภาพ
- เลย์เอาต์แบบฟอร์ม (Form layouts) ที่ป้ายกำกับและอินพุตต้องการให้ตรงกันทั้งในแนวนอนและแนวตั้ง
- เลย์เอาต์ใด ๆ ที่คุณกำลังคิดถึงแถว และ คอลัมน์ พร้อมกัน
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100dvh;
}
ตัวอย่างเปรียบเทียบข้างกัน: ตารางการ์ด (Card Grid)
นี่คือจุดที่ทำให้เกิดความสับสน ทั้งสองระบบสามารถสร้างแถวของการ์ดได้:
.card-row {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.card { flex: 1 1 280px; }
ด้วย Grid:
.card-row {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1rem;
}
ทั้งสองอย่างใช้งานได้ แต่เวอร์ชัน Grid มักจะได้รับความนิยมมากกว่าในที่นี้เพราะ auto-fill ร่วมกับ minmax ให้พฤติกรรมคอลัมน์ที่คาดการณ์ได้มากกว่า — แต่ละคอลัมน์จะมีความกว้างเท่ากันเป๊ะ และกริดจะจัดเรียงใหม่ได้อย่างสะอาดตา ส่วนเวอร์ชัน Flexbox จะดีกว่าเมื่อการ์ดสามารถมีความกว้างที่แปรผันได้และคุณต้องการให้พวกมันใช้พื้นที่ว่างที่มีอยู่อย่างลื่นไหล
ความแตกต่างของการจัดตำแหน่ง (Alignment Difference)
ใน Flexbox คุณจะจัดวางไอเทมตาม แกนหลัก (main axis) (ทิศทางที่คุณเลือก) และ แกนตัดขวาง (cross axis) (ซึ่งตั้งฉากกับมัน) คุณไม่สามารถควบคุมตำแหน่งของเซลล์ภายในกริดที่มองไม่เห็นของแถวและคอลัมน์แยกกันได้อย่างอิสระ
ใน Grid ทุกไอเทมจะอาศัยอยู่ในเซลล์ที่มีทั้งตำแหน่งแถวและคอลัมน์ คุณสามารถวางไอเทมที่แถว 2, คอลัมน์ 3 ได้อย่างชัดเจน หรือให้บราวเซอร์จัดวางให้อัตโนมัติ Flexbox ไม่มีแนวคิดเรื่อง "เซลล์" — ไอเทมจะแค่ไหลไปตามทิศทางที่คุณระบุ
ข้อผิดพลาดที่พบบ่อย
การใช้ Grid สำหรับการจัดกึ่งกลางง่าย ๆ: display: flex; align-items: center; justify-content: center นั้นเร็วกว่าการตั้งค่ากริดสำหรับองค์ประกอบเพียงตัวเดียว Flexbox ชนะในงานที่ต้องทำบนแกนเดียว
การใช้ Flexbox สำหรับเลย์เอาต์หน้าเว็บเต็มรูปแบบ: เมื่อคุณมีส่วนประกอบมากกว่าสองส่วนที่ต้องสัมพันธ์กันในเชิงตำแหน่ง (header + sidebar + content + footer) การขาดแกนที่สองของ Flexbox จะกลายเป็นปัญหา Grid จัดการเรื่องนี้ได้ด้วย named areas
การใช้ Flexbox column แทนที่จะเป็น Grid rows: flex-direction: column ช่วยให้ไอเทมซ้อนกันในแนวตั้ง แต่คุณจะเสียความสามารถในการจัดตำแหน่งเนื้อหาข้ามหลายคอลัมน์พร้อมกัน หากคุณกำลังคิดถึงเรื่อง "คอลัมน์" ให้เปลี่ยนไปใช้ Grid
การใช้งานร่วมกันทั้งคู่
Grid และ Flexbox ไม่ได้แยกจากกันโดยเด็ดขาด รูปแบบที่พบบ่อยที่สุดในโลกแห่งความเป็นจริงคือ Grid สำหรับเลย์เอาต์ระดับหน้าเว็บ, Flexbox ภายในแต่ละส่วน:
- Grid จัดตำแหน่ง sidebar, header และพื้นที่เนื้อหาหลัก
- ภายในแถบนำทาง (ซึ่งอยู่ในพื้นที่ header) Flexbox จะจัดการแถวของ logo + links + ปุ่ม CTA
- ในพื้นที่เนื้อหาหลัก ตารางการ์ดจะใช้ Grid สำหรับโครงสร้างคอลัมน์
- ภายในแต่ละการ์ด Flexbox จะจัดการเลย์เอาต์ icon + text + button
รูปแบบการประกอบนี้ — ใช้ Grid สำหรับโครงสร้าง, Flexbox สำหรับส่วนประกอบ (components) — คือวิธีที่เฟรมเวิร์ก CSS สมัยใหม่ส่วนใหญ่ (Tailwind, Bootstrap) ทำงานภายใน
ตารางอ้างอิงคุณสมบัติอย่างรวดเร็ว
| สิ่งที่คุณต้องการ | Flexbox | Grid |
|---|---|---|
| กำหนดทิศทางเลย์เอาต์ | flex-direction | grid-template-columns/rows |
| ระยะห่างระหว่างไอเทม | gap หรือ justify-content | gap |
| จัดตำแหน่งบนแกนตัดขวาง | align-items | align-items |
| วางไอเทมเฉพาะจุด | ไม่สามารถทำได้โดยตรง | grid-column / grid-row |
| ทำให้ไอเทมมีความสูงเท่ากัน | align-items: stretch | พฤติกรรมเริ่มต้น (Default) |
| Responsive โดยไม่ใช้ media queries | flex-wrap: wrap + flex-basis | auto-fill + minmax() |
สร้าง Layout ของ Flexbox ด้วยภาพ
ใช้เครื่องมือ Visual CSS Flexbox Generator ของเราเพื่อสร้าง flex containers, ปรับการจัดวาง และคัดลอก CSS ที่สร้างขึ้นได้ภายในไม่กี่วินาที