Category: guide
CSS Grid Advanced — Subgrid, Template Areas, Named Lines
เทคนิค Grid ระดับสูง: subgrid, named grid areas, auto-placement algorithm, และ grid ซ้อน grid
สารบัญ
ทบทวนพื้นฐานก่อน
Grid container สร้างด้วย display: grid ส่วน children จะกลายเป็น grid items อัตโนมัติ — ไม่ต้องทำอะไรเพิ่ม
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
Named Grid Lines
แทนที่จะนับ line number ตั้งชื่อได้:
.grid {
display: grid;
grid-template-columns:
[sidebar-start] 240px
[sidebar-end content-start] 1fr
[content-end];
}
.sidebar { grid-column: sidebar-start / sidebar-end; }
.content { grid-column: content-start / content-end; }
ชื่อ *-start / *-end ช่วย grid-area อ่านง่าย และ resize ง่ายกว่าการนับ column number
Grid Template Areas
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
min-height: 100svh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }
ข้อดี: เปลี่ยน layout responsive แค่เปลี่ยน grid-template-areas:
@media (max-width: 640px) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"content"
"sidebar"
"footer";
}
}
Subgrid
ปัญหาเก่า: ถ้า children มี grid ของตัวเอง column alignment จะไม่ตรงกับ parent
/* ❌ ก่อน subgrid */
.card { display: grid; grid-template-rows: auto 1fr auto; }
/* แต่ละ card มี row height ต่างกัน — alignment พัง */
Subgrid แก้ปัญหานี้:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto 1fr auto;
gap: 1rem;
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid; /* ใช้ row tracks ของ parent */
}
.card-title { /* ใช้ row 1 ของ parent */ }
.card-body { /* ใช้ row 2 — stretch เท่ากันทุก card */ }
.card-footer { /* ใช้ row 3 — อยู่บรรทัดเดียวกันทุก card */ }
Browser support: Chrome 117+, Firefox 71+, Safari 16+ — ใช้ได้แล้วในปี 2024+
Auto-placement Algorithm
Grid วาง items โดยอัตโนมัติตาม grid-auto-flow:
/* default: row — เติมแนวนอน */
.grid { grid-auto-flow: row; }
/* column — เติมแนวตั้ง */
.grid { grid-auto-flow: column; }
/* dense — เติมช่องว่างด้วย items ที่เล็กกว่า */
.grid { grid-auto-flow: row dense; }
dense มีประโยชน์กับ gallery ที่ items มี span ต่างกัน:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-flow: row dense;
gap: 1rem;
}
.featured { grid-column: span 2; grid-row: span 2; }
auto-fill vs auto-fit
/* auto-fill: สร้าง track แม้ไม่มี item */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* auto-fit: ยุบ track ที่ว่าง ทำให้ items stretch เต็ม container */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
- auto-fill → items อยู่ตำแหน่งเดิม ถ้าน้อยกว่า column จะมีช่องว่าง
- auto-fit → items stretch เต็ม แนะนำสำหรับ card grid ทั่วไป
Grid ซ้อน Grid
.outer {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 1.5rem;
}
.inner {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
/* inner grid ไม่เกี่ยวกับ outer grid เลย — independent */
}
ใช้ subgrid ถ้าต้องการ alignment ข้าม nesting level:
.inner {
display: grid;
grid-column: 1 / -1; /* span ทุก column ของ parent */
grid-template-columns: subgrid;
}
Implicit vs Explicit Grid
- Explicit grid = tracks ที่กำหนดด้วย
grid-template-columns/rows - Implicit grid = tracks ที่ browser สร้างอัตโนมัติเมื่อ items เกิน
ควบคุม implicit tracks ด้วย:
.grid {
grid-template-columns: repeat(3, 1fr); /* explicit: 3 columns */
grid-auto-rows: minmax(120px, auto); /* implicit rows: ขั้นต่ำ 120px */
}
Alignment ใน Grid
.grid {
/* ทั้ง grid */
justify-content: center; /* แนวนอน: ทั้ง grid ใน container */
align-content: start; /* แนวตั้ง: ทั้ง grid ใน container */
/* แต่ละ cell */
justify-items: stretch; /* items ใน cell แนวนอน */
align-items: center; /* items ใน cell แนวตั้ง */
}
.item {
/* override สำหรับ item เดียว */
justify-self: end;
align-self: start;
}
Pattern: Holy Grail Layout
.page {
display: grid;
grid-template:
"header" auto
"main" 1fr
"footer" auto
/ 1fr;
min-height: 100dvh;
}
@media (min-width: 900px) {
.page {
grid-template:
"header header header" auto
"nav main aside" 1fr
"footer footer footer" auto
/ 200px 1fr 200px;
}
}
Pattern: Masonry (CSS-native, experimental)
Chrome 125+ รองรับ masonry layout ผ่าน Grid:
.masonry {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: masonry; /* experimental */
gap: 1rem;
}
ยังต้องใช้ @supports จนกว่า browser support จะครบ
Debugging Grid
Chrome/Firefox DevTools มี grid overlay:
- คลิก grid badge ข้างๆ element ใน Elements panel
- เปิด line numbers, area names, track sizes overlay
- ใช้ “Computed” tab ดู final grid track values
/* ช่วย visualize ตอน debug */
.grid * { outline: 1px dashed rgba(0, 128, 255, 0.3); }