CSS
Grid
display: grid
เรียนรู้ว่า display: grid เปลี่ยน parent ให้กลายเป็น Grid Container ที่จัด layout แบบสองมิติได้อย่างไร และทำไม CSS Grid ถึงเป็นเครื่องมือที่ขาดไม่ได้สำหรับการทำ layout หน้าเว็บสมัยใหม่
หัวข้อนี้คืออะไร
CSS มี property ชื่อ display ที่บอก browser ว่าควรจัดวาง element แบบใด เมื่อคุณเขียน display: grid บน element ใดก็ตาม element นั้นจะกลายเป็น กริดคอนเทนเนอร์ (Grid Container) ทันที และ element ลูกทั้งหมดที่อยู่ข้างในจะกลายเป็น กริดไอเท็ม (Grid Items) โดยอัตโนมัติ สิ่งที่ Grid แตกต่างจาก layout ปกติคือ browser เปลี่ยนโหมดการจัดวางจาก block layout (วางซ้อนกันจากบนลงล่าง) มาเป็น grid layout ซึ่งจัดวางลูกในแบบสองมิติ คือทั้งแถว (Row) และคอลัมน์ (Column) พร้อมกัน สิ่งสำคัญที่ต้องจำ: - display: grid กำหนดที่ parent ไม่ใช่ child - ผลจะส่งไปยัง child ทุกตัวที่อยู่โดยตรงใน parent นั้น - เหมาะที่สุดสำหรับ layout ที่มีโครงสร้างเป็นช่อง ๆ
- display: grid ทำให้ element นั้นกลายเป็น Grid Container
- element ลูกทุกตัวภายในจะกลายเป็น Grid Items โดยอัตโนมัติ
- Grid จัดวางในแบบสองมิติ — ทั้งแถว (Row) และคอลัมน์ (Column) พร้อมกัน
- กฎนี้กำหนดที่ parent ผลจึงส่งไปยัง child ทุกตัวที่อยู่โดยตรงข้างใน
ทำไมหัวข้อนี้จึงสำคัญ
ก่อนมี CSS Grid การทำ layout ที่เป็นช่อง ๆ หลายคอลัมน์ต้องใช้เทคนิคที่ซับซ้อน เช่น float, inline-block, หรือ position absolute ซึ่งทั้งหมดมีข้อจำกัดและพฤติกรรมที่คาดเดาได้ยาก display: grid แก้ปัญหานั้นได้อย่างตรงจุด โดยเฉพาะ layout ที่ต้องการกำหนดโครงสร้างทั้งแนวนอนและแนวตั้งในคราวเดียว สิ่งที่ Grid ช่วยได้ทันที:
- Page layout — จัดหน้าเว็บทั้งหน้าให้มี sidebar, header, main, footer
- Card grid — วาง card หลายใบเป็นตาราง เช่น ร้านค้าออนไลน์
- Photo gallery — เรียงรูปภาพหลายรูปเป็นแถวและคอลัมน์
- Dashboard — จัดวาง widget หลายชิ้นในแบบตารางข้อมูล
- เป็นพื้นฐานก่อนเรียน grid-template-columns, grid-area และ property อื่น ๆ ของ Grid
ตัวอย่างจากชีวิตจริง
ลองนึกถึงหน้าหนังสือพิมพ์ หนังสือพิมพ์มีโครงสร้างที่ชัดเจน — หัวข้อข่าวใหญ่ครองพื้นที่บนสุด รองลงมาเป็นคอลัมน์ข่าวย่อย 3 คอลัมน์เคียงกัน และด้านล่างสุดมีโฆษณาคาดยาวเต็มแถว บรรณาธิการไม่ได้บอกให้ข่าวแต่ละชิ้นจัดตำแหน่งตัวเอง — บรรณาธิการออกแบบ "ตารางเค้าโครง" ของหน้ากระดาษก่อน แล้วเนื้อหาจะถูกวางลงในช่องที่กำหนด display: grid ทำงานแบบเดียวกัน คุณกำหนดโครงตารางที่ parent (Grid Container) — แล้ว browser จะวาง children ลงในช่อง (Grid Items) โดยอัตโนมัติ ต่างจาก block layout ที่ each element ดูแลตัวเอง Grid ให้ parent เป็นผู้ควบคุมโครงสร้างทั้งหมด
แนวคิดหลักที่ต้องเข้าใจ
มีสองบทบาทหลักใน CSS Grid: กริดคอนเทนเนอร์ (Grid Container) — element ที่ได้รับ display: grid คือ parent ที่คุณเขียน CSS ลงไป element นี้ทำหน้าที่กำหนดโครงสร้างตารางสำหรับลูกทั้งหมดข้างใน กริดไอเท็ม (Grid Items) — element ลูกโดยตรงของ container ทุก child ที่อยู่ภายใน container โดยตรงจะกลายเป็น grid item อัตโนมัติ ไม่ต้องเขียน CSS ที่ลูกเพิ่มเติมใด ๆ Grid จัดการสองมิติพร้อมกัน: - แถว (Row) — แนวนอน จากซ้ายไปขวา - คอลัมน์ (Column) — แนวตั้ง จากบนลงล่าง ความแตกต่างจาก Flex: - Flex เด่นเรื่องหนึ่งมิติ — จัดเรียง element ในแนวแถวหรือแนวคอลัมน์อย่างใดอย่างหนึ่ง - Grid เด่นเรื่องสองมิติ — กำหนดโครงสร้างทั้งแถวและคอลัมน์พร้อมกันได้ในคราวเดียว ในบทนี้เราจะโฟกัสที่การเปิด grid ก่อน property ที่ใช้กำหนดจำนวน column จะเรียนในบทถัดไป
Grid Container = parent ที่ได้รับ display: grid | Grid Items = children ทุกตัวข้างใน | Grid จัดวางทั้งแถวและคอลัมน์พร้อมกัน
การทำงานทีละขั้นตอน
นี่คือสิ่งที่เกิดขึ้นเมื่อ browser พบ display: grid:
- 1. สร้าง parent element — เช่น <div class="container"> นี่คือ element ที่จะกลายเป็น grid container
- 2. ใส่ child elements ไว้ข้างใน — เช่น <div class="item"> สี่ตัว ตอนนี้พวกมันยังเป็น block ซ้อนกันจากบนลงล่าง
- 3. กำหนด display: grid ที่ parent — เขียน .container { display: grid; } ใน CSS ของคุณ
- 4. browser เปลี่ยนโหมด — parent กลายเป็น grid container ทันที ลูกทุกตัวกลายเป็น grid items
- 5. ผลลัพธ์ — browser วาง grid items ลงในช่องตารางโดยอัตโนมัติ ค่าเริ่มต้นคือหนึ่งคอลัมน์ (items ยังซ้อนกัน) การกำหนดจำนวน column ที่ต้องการจะทำในบทถัดไปด้วย grid-template-columns
ตัวอย่างเชิงเทคนิค — ก่อนและหลัง display: grid
ลองดูความแตกต่างระหว่าง container ปกติกับ container ที่เป็น grid โค้ดด้านล่างมีกล่องสี่ใบอยู่ใน .without-grid และ .with-grid .without-grid ใช้ block ปกติ ดังนั้นกล่องสี่ใบซ้อนกันจากบนลงล่าง .with-grid ใช้ display: grid — browser สร้าง grid context ให้ทันที items วางตัวในตาราง สังเกตว่า: แม้จะใช้ display: grid แล้ว items ยังคงเรียงเป็นคอลัมน์เดียวอยู่ นั่นเป็นเพราะยังไม่ได้กำหนด grid-template-columns ซึ่งจะเรียนในบทถัดไป
จุดที่ผู้เริ่มต้นมักสับสน
ตรวจสอบว่าคุณเข้าใจถูกต้องหรือยัง:
- ❌ ใส่ display: grid ที่ลูกแทน parent — ความผิดพลาดที่พบบ่อยที่สุด grid ต้องอยู่ที่ parent (container) เสมอ ถ้าใส่ที่ลูก ลูกนั้นจะกลายเป็น container ของ "ลูกของลูก" ไม่ใช่เรียงตัวเองกับพี่น้อง
- ❌ คาดหวังว่า display: grid จะจัด layout หลายคอลัมน์ได้เอง — display: grid เพียงอย่างเดียวสร้าง grid context แต่ค่าเริ่มต้นคือ 1 คอลัมน์ หากต้องการหลายคอลัมน์ต้องใช้ grid-template-columns เพิ่มเติม ซึ่งจะเรียนในบทถัดไป
- ❌ สับสนระหว่าง Grid กับ Flex — Flex เด่นเรื่องหนึ่งมิติ เหมาะกับ navigation bar, toolbar, card row Grid เด่นเรื่องสองมิติ เหมาะกับ page layout, photo gallery, dashboard ที่ต้องการกำหนดทั้งแถวและคอลัมน์
- ❌ คิดว่า Grid และ Flex ใช้ร่วมกันไม่ได้ — ในความเป็นจริงใช้ร่วมกันได้ดีมาก เช่น ใช้ Grid สำหรับ page layout หลัก แล้วใช้ Flex ภายใน card แต่ละใบ
เปรียบเทียบ block / flex / grid layout
สรุปความแตกต่างหลักในตารางเดียว:
| พฤติกรรม | block layout (ปกติ) | flex layout (display: flex) | grid layout (display: grid) |
|---|---|---|---|
| มิติการจัดวาง | หนึ่งมิติ (บนลงล่าง) | หนึ่งมิติ (แถวหรือคอลัมน์) | สองมิติ (แถวและคอลัมน์พร้อมกัน) |
| ทิศทางเริ่มต้น | ซ้อนกันจากบนลงล่าง | เรียงจากซ้ายไปขวา (row) | เรียงลงในช่องตาราง (1 คอลัมน์ถ้าไม่กำหนด) |
| ผู้กำหนดกฎ | แต่ละ element ดูแลตัวเอง | parent ควบคุมลูกตามแกนหลัก | parent กำหนดโครงสร้างตารางทั้งหมด |
| เหมาะกับอะไร | โครงสร้างเอกสารทั่วไป | navigation, card row, toolbar, header | page layout, photo gallery, dashboard, card grid |
| การจัดหลายคอลัมน์ | ยุ่งยาก ต้องใช้ float หรือ position | ทำได้ผ่าน flex-wrap แต่ไม่ใช่จุดแข็ง | ทำได้ง่ายมากด้วย grid-template-columns |
สรุปท้ายบท
จำง่าย ๆ แบบนี้: "display: grid กำหนดที่ parent เพื่อสร้างโครงตารางให้ลูก"
- display: grid ทำให้ parent กลายเป็น Grid Container
- ลูกทุกตัวภายใน container กลายเป็น Grid Items อัตโนมัติ
- Grid จัดวางแบบสองมิติ — ทั้งแถว (Row) และคอลัมน์ (Column) พร้อมกัน
- กฎ grid กำหนดที่ parent — ไม่ใช่ที่ลูก
- ค่าเริ่มต้น: 1 คอลัมน์ — ต้องใช้ grid-template-columns เพื่อกำหนดจำนวน column
- Grid เด่นเรื่องสองมิติ, Flex เด่นเรื่องหนึ่งมิติ — ใช้ร่วมกันได้
Lab 1: เปลี่ยน container ให้เป็น grid
ชื่อ Lab: เปิด Grid Container ครั้งแรก เป้าหมาย: กำหนด display: grid ที่ parent ให้ถูก element และสังเกตว่า browser สร้าง grid context ทันที โจทย์: ตอนนี้กล่อง 1, 2, 3, 4 ซ้อนกันจากบนลงล่าง เพราะ .container ยังใช้ block layout ปกติ เพิ่ม display: grid ให้ .container เพื่อเปลี่ยนให้เป็น grid container เงื่อนไข: - ต้องกำหนด display: grid ที่ selector .container เท่านั้น - ห้ามแตะ CSS ของ .box ระบบจะตรวจ: 1. .container มี display: grid ใน CSS 2. computed display ของ .container = grid ใน browser 3. .box ทุกใบอยู่ใน .container และแสดงผลได้ แนวทางการคิด: grid กำหนดที่ parent เสมอ ดูว่า element ไหนคือ parent ของกล่องทั้งสี่
Lab 2: สร้าง photo grid พื้นฐาน
ชื่อ Lab: สร้าง Photo Grid ด้วย CSS Grid เป้าหมาย: ใช้ display: grid บน .gallery เพื่อให้ browser สร้าง grid context สำหรับรูปภาพทั้ง 6 ช่อง โจทย์: ตอนนี้ .gallery มีช่องรูปภาพอยู่ 6 ช่อง แต่ยังซ้อนกันจากบนลงล่างเพราะใช้ block layout กำหนด display: grid ที่ .gallery เพื่อสร้าง grid context เงื่อนไข: - ต้องกำหนด display: grid ที่ .gallery - ห้ามเปลี่ยน CSS ของ .photo ระบบจะตรวจ: 1. .gallery มี display: grid ใน CSS 2. computed display ของ .gallery = grid ใน browser 3. .photo ทุกช่อง (6 ช่อง) อยู่ใน .gallery แนวทางการคิด: หา element ที่เป็น parent ของ .photo ทุกตัว นั่นคือ element ที่ต้องได้รับ display: grid
Lab 3: แก้ dashboard จาก block เป็น grid
ชื่อ Lab: แปลง Dashboard จาก Block เป็น Grid Layout เป้าหมาย: แก้โค้ด dashboard ที่มีอยู่ให้เปลี่ยนจาก block layout มาเป็น grid layout โดยเพิ่ม property เดียว โจทย์: โค้ดด้านล่างมี .dashboard ที่ประกอบด้วย .widget สี่ชิ้น ตอนนี้ทุก widget ซ้อนกันจากบนลงล่าง ซึ่งไม่ใช่ลักษณะของ dashboard จริง เพิ่ม display: grid ให้ .dashboard เพื่อสร้าง grid context เงื่อนไข: - ต้องกำหนด display: grid ที่ .dashboard เท่านั้น - ห้ามแก้ HTML - ห้ามแก้ CSS ของ .widget ระบบจะตรวจ: 1. .dashboard มีอยู่ใน HTML 2. .dashboard มี display: grid ใน CSS 3. computed display ของ .dashboard = grid ใน browser 4. .widget ทั้ง 4 ชิ้นอยู่ใน .dashboard แนวทางการคิด: dashboard จริงมี widget หลายชิ้นในโครงตาราง parent ของพวกมันคือตัวที่ต้องได้รับ grid