CSS
Grid
grid-area
เรียนรู้วิธีกำหนดตำแหน่งและขนาดของ grid item ด้วย grid-area — ทำให้ item หนึ่งชิ้นกินพื้นที่ได้หลายช่อง และจัด layout ที่ซับซ้อนได้ด้วยโค้ดที่อ่านง่าย
หัวข้อนี้คืออะไร
ในบทที่ผ่านมาเราใช้ grid-template-columns กำหนดจำนวนคอลัมน์ และ gap กำหนดช่องว่าง แต่ทุก item ยังคงถูกวางเรียงตามลำดับอัตโนมัติ ช่องละหนึ่ง item เท่านั้น grid-area คือ property ที่ให้คุณบอก item แต่ละชิ้นว่า "อยู่ตรงไหน" และ "กินพื้นที่กว้างแค่ไหน" ในกริด ด้วย grid-area คุณสามารถทำได้สองสิ่ง: ① วาง item ในตำแหน่งเฉพาะ — เช่น วางไว้แถวที่ 2 คอลัมน์ที่ 1 ② ทำให้ item กินพื้นที่มากกว่าหนึ่งช่อง — เช่น กินสองคอลัมน์หรือสองแถว (span) สิ่งสำคัญที่ต้องจำ: - grid-area กำหนดที่ child (Grid Item) ไม่ใช่ที่ parent - ใช้ร่วมกับ display: grid และ grid-template-columns เสมอ - มีสองรูปแบบหลัก: ใช้ชื่อพื้นที่ หรือระบุเส้น (line numbers)
- grid-area กำหนดที่ Grid Item (child) — ต่างจาก grid-template-columns ที่กำหนดที่ container
- item หนึ่งชิ้นสามารถกินพื้นที่ได้หลายช่อง ทั้งแนวนอนและแนวตั้ง
- ใช้ grid-column: span 2 เพื่อให้ item กินสองคอลัมน์
- ใช้ grid-row: span 2 เพื่อให้ item กินสองแถว
- grid-area ช่วยสร้าง layout ที่ซับซ้อนได้โดยไม่ต้องแก้ HTML
ทำไมหัวข้อนี้จึงสำคัญ
layout จริงในโลกจริงไม่ได้มีทุก item ขนาดเท่ากันเสมอไป หน้าข่าว — ข่าวหลักใหญ่กว่าข่าวรอง หน้า e-commerce — สินค้า featured ใหญ่กว่าสินค้าปกติ Dashboard — widget สรุปกว้างกว่า widget ข้อมูลเล็ก Blog — featured post คาดเต็มแถว ข้อด้านล่างเรียงตามปกติ โดยไม่มี grid-area คุณต้องแก้ HTML เพิ่มกล่องซ้อนกัน หรือใช้ position absolute ซึ่งซับซ้อนและบำรุงรักษายาก ด้วย grid-area คุณเพิ่มแค่ CSS ที่ item ที่ต้องการ layout เปลี่ยนได้ทันที
- Featured article — คาดเต็มแถวบนสุดด้วย grid-column: span 3
- Hero banner — item ใหญ่กินสองคอลัมน์สองแถว
- Dashboard widget — widget สรุปกว้างกว่าข้อมูลย่อย
- Magazine layout — ภาพใหญ่ซ้าย บทความเล็กขวาหลายใบ
- Card grid ที่มีขนาดผสม — featured card ใหญ่กว่า card ปกติ
ตัวอย่างจากชีวิตจริง
ลองนึกถึงกระดานแม่เหล็กในครัวที่ใช้ติดกระดาษโน้ต ปกติคุณวางโน้ตกระดาษขนาดเดียวกันเรียงเป็นตาราง ช่องละหนึ่งใบ แต่บางครั้งคุณต้องการเขียนรายการซื้อของที่ยาวมาก — คุณก็เอากระดาษขนาดใหญ่มาปิดทับสองช่องหรือสี่ช่อง กระดาษใหญ่นั้นไม่ได้ทำให้กระดานขยาย — มันแค่ใช้พื้นที่มากกว่าหนึ่งช่อง grid-area ทำงานแบบเดียวกัน คุณบอก item ว่า "กินพื้นที่สองช่องนะ" — item นั้นก็ขยายตัวข้ามช่องคอลัมน์หรือแถวที่อยู่ถัดไป โดย item อื่น ๆ ที่เหลือก็วางเรียงกันในช่องที่เหลือตามปกติ
แนวคิดหลักที่ต้องเข้าใจ
มีสองวิธีหลักในการใช้ grid-area ในบทนี้จะเน้นแบบที่ 1 และ 2: ① grid-column: span N ทำให้ item กินพื้นที่กว้าง N คอลัมน์ grid-column: span 2; → item นี้กินสองคอลัมน์ grid-column: span 3; → item นี้กินสามคอลัมน์ ② grid-row: span N ทำให้ item กินพื้นที่สูง N แถว grid-row: span 2; → item นี้กินสองแถว ③ grid-area: row-start / col-start / row-end / col-end (advanced) กำหนดตำแหน่งแบบระบุเส้น — เหมาะกับ layout ที่ซับซ้อน ตัวอย่าง: grid-area: 1 / 1 / 3 / 3; → วางจากแถว 1 คอลัมน์ 1 ถึงแถว 3 คอลัมน์ 3 ข้อสำคัญ: grid-column และ grid-row กำหนดที่ item เสมอ ไม่ใช่ที่ container
grid-column: span 2 = กินสองคอลัมน์ | grid-row: span 2 = กินสองแถว | กำหนดที่ item ไม่ใช่ container
การทำงานทีละขั้นตอน
นี่คือขั้นตอนการทำให้ item กินพื้นที่มากกว่าหนึ่งช่อง:
- 1. เตรียม grid container — ต้องมี display: grid และ grid-template-columns ก่อนเสมอ
- 2. ระบุว่า item ไหนต้องการพื้นที่พิเศษ — เช่น การ์ดใบแรกต้องการกินสองคอลัมน์
- 3. เพิ่ม grid-column: span 2 ที่ item นั้น — บอกให้มันกินสองคอลัมน์
- 4. browser จัดวาง items ที่เหลือโดยอัตโนมัติ — items อื่นจะเลื่อนไปวางในช่องที่เหลือ
- 5. ถ้าต้องการกินหลายแถวด้วย — ใช้ grid-row: span 2 เพิ่มเติมที่ item เดียวกัน
ตัวอย่างเชิงเทคนิค — item ปกติ vs item ที่ span
ลองดูความแตกต่างระหว่าง item ปกติกับ item ที่กินพื้นที่มากกว่าหนึ่งช่อง กริดด้านบนมี 4 items เรียงปกติในกริด 2 คอลัมน์ กริดด้านล่างมี item แรกที่ใช้ grid-column: span 2 จึงกินพื้นที่เต็มแถวบนสุด สังเกตว่า items ที่เหลือถูกเลื่อนลงโดยอัตโนมัติ
จุดที่ผู้เริ่มต้นมักสับสน
ตรวจสอบว่าคุณเข้าใจถูกต้องหรือยัง:
- ❌ ใส่ grid-column: span ที่ container แทน item — span กำหนดที่ item เสมอ ไม่ใช่ที่ container ถ้าใส่ที่ container จะไม่มีผล
- ❌ span เกินจำนวนคอลัมน์ที่มี — ถ้ากริดมีแค่ 2 คอลัมน์แต่ span 3 browser จะสร้างคอลัมน์เพิ่มให้อัตโนมัติ ซึ่งมักไม่ใช่สิ่งที่ต้องการ
- ❌ สับสนระหว่าง grid-column กับ grid-column-start — grid-column: span 2 ย่อมาจากการระบุจุดเริ่มและจุดสิ้นสุดของคอลัมน์ในแบบสั้น เหมาะกว่าสำหรับผู้เริ่มต้น
- ❌ คิดว่า span อัตโนมัติจะจัดตำแหน่งให้สวยเสมอ — span บอกแค่ว่า item กว้างแค่ไหน ไม่ได้บอกว่าอยู่ตรงไหน ตำแหน่งยังคงขึ้นกับลำดับใน HTML และพื้นที่ว่างในกริด
เปรียบเทียบวิธีการวาง item
มีหลายวิธีในการควบคุมตำแหน่ง item ในกริด เลือกให้เหมาะกับงาน:
| วิธี | ตัวอย่าง | เหมาะกับ |
|---|---|---|
| อัตโนมัติ (ไม่กำหนด) | (ไม่มี CSS เพิ่ม) | items ขนาดเท่ากันเรียงตามลำดับ |
| grid-column: span N | grid-column: span 2 | ให้ item กินกว้าง N คอลัมน์ |
| grid-row: span N | grid-row: span 2 | ให้ item กินสูง N แถว |
| grid-column: start / end | grid-column: 1 / 3 | ระบุตำแหน่งเส้นเริ่มและสิ้นสุดแม่นยำ |
| grid-area: r / c / re / ce | grid-area: 1 / 1 / 3 / 3 | กำหนดทั้งแถวและคอลัมน์พร้อมกันแบบ advanced |
สรุปท้ายบท
จำง่าย ๆ แบบนี้: "grid-area / span กำหนดที่ item — บอกให้ item กินพื้นที่มากกว่าหนึ่งช่อง"
- grid-column และ grid-row กำหนดที่ Grid Item (child) ไม่ใช่ container
- grid-column: span 2 = item นี้กินสองคอลัมน์
- grid-row: span 2 = item นี้กินสองแถว
- items อื่น ๆ จะวางในช่องที่เหลือโดยอัตโนมัติ
- span ไม่เกินจำนวนคอลัมน์ที่กำหนดใน grid-template-columns
- ใช้ทั้ง grid-column และ grid-row พร้อมกันได้เพื่อให้ item กินพื้นที่สี่เหลี่ยมใหญ่
Lab 1: ทำให้ item กินสองคอลัมน์
ชื่อ Lab: Featured Item ที่กินสองคอลัมน์ เป้าหมาย: ใช้ grid-column: span 2 ที่ .featured เพื่อให้มันกินพื้นที่เต็มแถวบนสุด โจทย์: .grid มีกริด 2 คอลัมน์ มี item อยู่ 4 ใบ .featured คือ item แรกที่ต้องการกินพื้นที่สองคอลัมน์เพื่อเป็น featured card เพิ่ม grid-column: span 2 ให้ .featured เงื่อนไข: - ต้องกำหนด grid-column: span 2 ที่ .featured - ห้ามแก้ HTML ระบบจะตรวจ: 1. .featured มี grid-column ที่มีค่า span ใน CSS 2. computed width ของ .featured กว้างกว่า .card ปกติ แนวทางการคิด: span กำหนดที่ item ไม่ใช่ container หา selector ของ item ที่ต้องการขยาย
Lab 2: ทำให้ item กินสองแถว
ชื่อ Lab: Hero Image ที่กินสองแถว เป้าหมาย: ใช้ grid-row: span 2 ที่ .hero เพื่อให้มันกินพื้นที่สูงสองแถว โจทย์: .layout มีกริด 2 คอลัมน์ .hero อยู่ซ้าย ควรสูงเท่ากับสองแถวของ item ขวา เพิ่ม grid-row: span 2 ให้ .hero เงื่อนไข: - ต้องกำหนด grid-row: span 2 ที่ .hero - ห้ามแก้ HTML ระบบจะตรวจ: 1. .hero มี grid-row ที่มีค่า span ใน CSS 2. computed height ของ .hero สูงกว่า .side-item ปกติ แนวทางการคิด: span บนแนวตั้งคือ grid-row ไม่ใช่ grid-column
Lab 3: จัด mini layout ด้วย grid-area
ชื่อ Lab: Magazine Layout — Featured + Articles เป้าหมาย: ทำให้ .feature-article กินสองแถวในกริด 3 คอลัมน์ เพื่อสร้าง magazine layout โจทย์: .magazine มีกริด 3 คอลัมน์ .feature-article ควรกินทั้งหมด 2 แถวในคอลัมน์แรก (grid-row: span 2) และ .article ทั้งสี่ใบควรอยู่ในคอลัมน์ที่เหลือ เงื่อนไข: - ต้องกำหนด grid-row: span 2 ที่ .feature-article - ห้ามแก้ HTML ระบบจะตรวจ: 1. .magazine มีอยู่ใน HTML 2. .feature-article มี grid-row ที่มีค่า span ใน CSS 3. .feature-article สูงกว่า .article ทั่วไป 4. มี .article อย่างน้อย 4 ใบใน .magazine แนวทางการคิด: feature article ควรสูงเท่ากับแถวที่ article ย่อยสองแถวรวมกัน ใช้ grid-row: span 2