Article · programming
HTML และ CSS EP18: CSS Grid Layout — สร้างเลย์เอาต์เว็บไซต์แบบหลายคอลัมน์อย่างมืออาชีพ
HTML & CSS
บทเรียน EP18 เรียนรู้ CSS Grid ตั้งแต่แนวคิดแถวและคอลัมน์ การกำหนดพื้นที่ การสร้างการ์ดสินค้าแบบ Responsive การใช้ minmax(), repeat(), auto-fit และ grid-template-areas พร้อมตัวอย่าง HTML เต็มหน้าและแบบฝึกหัดที่นำไปทดลองได้ทันที
EP18 — CSS Grid Layout: วางโครงสร้างเว็บไซต์ด้วยแถวและคอลัมน์
เมื่อเว็บไซต์มีเนื้อหาหลายส่วน เช่น เมนูนำทาง แถบด้านข้าง พื้นที่บทความ การ์ดสินค้า และส่วนท้าย การจัดวางด้วยการกำหนดระยะทีละชิ้นอาจทำให้แก้ไขยากขึ้น CSS Grid เป็นระบบเลย์เอาต์สองมิติที่ช่วยจัดองค์ประกอบทั้งแนวนอนและแนวตั้งได้อย่างเป็นระบบ เหมาะกับหน้ารวมสินค้า แกลเลอรี แดชบอร์ด หน้าบทความ และโครงสร้างหน้าเว็บไซต์ที่มีหลายส่วน
เป้าหมายของบทเรียนหลังเรียนจบ คุณจะสามารถสร้าง Grid Container และ Grid Items กำหนดจำนวนคอลัมน์และแถว จัดพื้นที่ด้วย grid-template-areas สร้างการ์ดที่ปรับจำนวนคอลัมน์อัตโนมัติ และนำ CSS Grid ไปใช้ร่วมกับ Flexbox ได้อย่างเหมาะสม
1. CSS Grid คืออะไร และต่างจาก Flexbox อย่างไร
**CSS Grid** เป็นระบบจัดวางองค์ประกอบที่ออกแบบมาเพื่อควบคุมทั้งสองแกนพร้อมกัน ได้แก่ แถว (Rows) และคอลัมน์ (Columns) โดยองค์ประกอบที่อยู่ภายใน Grid Container จะกลายเป็น Grid Items ส่วน **Flexbox** เหมาะกับการจัดองค์ประกอบตามแกนหลักหนึ่งแกนในแต่ละคอนเทนเนอร์ เช่น เรียงเมนูเป็นแถวหรือจัดปุ่มให้อยู่ชิดขวา ทั้งสองระบบสามารถใช้ร่วมกันในหน้าเดียวได้ ไม่จำเป็นต้องเลือกใช้เพียงอย่างใดอย่างหนึ่ง
| หัวข้อ | CSS Grid | Flexbox |
|---|---|---|
| ลักษณะการจัดวาง | สองมิติ: แถวและคอลัมน์ | หนึ่งมิติเป็นหลัก: แถวหรือคอลัมน์ |
| กรณีใช้งาน | โครงสร้างหน้า แกลเลอรี และกริดสินค้า | เมนู ปุ่ม แถบเครื่องมือ และกลุ่มรายการ |
| การกำหนดพื้นที่ | กำหนดเส้นกริดและพื้นที่ชื่อได้ | จัดขนาดและการกระจายพื้นที่ตามแกน |
| การทำงานร่วมกัน | ใช้จัดโครงสร้างภายนอกและภายในได้ | ใช้จัดองค์ประกอบภายในแต่ละส่วนได้ |
2. คำศัพท์พื้นฐานที่ต้องเข้าใจ
- **Grid Container:** องค์ประกอบแม่ที่กำหนด `display: grid`\n- **Grid Item:** องค์ประกอบลูกโดยตรงภายใน Grid Container\n- **Grid Track:** ช่องว่างตามแนวแถวหรือคอลัมน์ที่กริดสร้างขึ้น\n- **Grid Line:** เส้นแบ่งขอบเขตของแถวหรือคอลัมน์\n- **Grid Cell:** ช่องหนึ่งช่องที่เกิดจากจุดตัดของแถวและคอลัมน์\n- **Grid Area:** พื้นที่ที่ครอบคลุมหนึ่งช่องหรือหลายช่องในกริด\n- **Gap:** ระยะห่างระหว่างแถวและคอลัมน์
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Grid พื้นฐาน</title>
<style>
* { box-sizing: border-box; }
body { margin: 0; padding: 24px; font-family: system-ui, sans-serif; background: #f1f5f9; color: #172033; }
h1 { font-size: 1.5rem; }
.grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }
.item { padding: 24px 12px; text-align: center; color: #fff; background: #2563eb; border-radius: 10px; font-weight: 700; }
.item:nth-child(even) { background: #0f766e; }
@media (max-width: 520px) { .grid { grid-template-columns: 1fr 1fr; } }
</style>
</head>
<body>
<h1>ตัวอย่าง Grid 3 คอลัมน์</h1>
<p>ทดลองปรับความกว้างหน้าต่างเพื่อดูจำนวนคอลัมน์เปลี่ยนไป</p>
<div class="grid">
<div class="item">รายการ 1</div>
<div class="item">รายการ 2</div>
<div class="item">รายการ 3</div>
<div class="item">รายการ 4</div>
<div class="item">รายการ 5</div>
<div class="item">รายการ 6</div>
</div>
</body>
</html>
3. เริ่มต้นสร้าง Grid ด้วย display: grid
ขั้นแรกกำหนด `display: grid` ให้กับองค์ประกอบแม่ จากนั้นใช้ `grid-template-columns` เพื่อกำหนดคอลัมน์ ตัวอย่าง `grid-template-columns: 200px 1fr 1fr;` จะสร้างคอลัมน์แรกกว้าง 200 พิกเซล และแบ่งพื้นที่ที่เหลือให้คอลัมน์ที่สองกับสามเท่า ๆ กัน ค่า `fr` หมายถึงส่วนแบ่งของพื้นที่ว่างในกริด ไม่ใช่หน่วยพิกเซลตายตัว
.layout {
display: grid;
grid-template-columns: 200px 1fr 1fr;
gap: 16px;
}
/* คอลัมน์กว้างเท่ากัน 3 คอลัมน์ */
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
/* แถวที่มีความสูงอย่างน้อย 120px */
.cards {
grid-auto-rows: minmax(120px, auto);
}
4. repeat(), minmax() และ auto-fit: หัวใจของ Responsive Grid
การเขียนจำนวนคอลัมน์ตายตัวอาจไม่เหมาะกับทุกขนาดหน้าจอ เราสามารถใช้ `repeat()` ลดการเขียนซ้ำ ใช้ `minmax()` ระบุขนาดต่ำสุดและสูงสุด และใช้ `auto-fit` เพื่อให้เบราว์เซอร์จัดจำนวนคอลัมน์ตามพื้นที่ที่มีอยู่ รูปแบบที่ใช้บ่อยคือ `grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));` ซึ่งพยายามสร้างคอลัมน์ที่มีความกว้างอย่างน้อย 220 พิกเซล แล้วแบ่งพื้นที่ว่างให้เหมาะสม
เทคนิคที่ใช้ได้จริงสำหรับกริดการ์ดสินค้า การ์ดบทความ หรือแกลเลอรีที่ไม่จำเป็นต้องมีจำนวนคอลัมน์เท่ากันทุกอุปกรณ์ ให้เริ่มทดลองจาก repeat(auto-fit, minmax(220px, 1fr)) แล้วปรับค่าความกว้างขั้นต่ำตามเนื้อหาและการออกแบบ
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 20px;
}
.product-card {
min-width: 0;
padding: 20px;
border: 1px solid #e2e8f0;
border-radius: 14px;
background: #fff;
}
.product-card img {
display: block;
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
border-radius: 10px;
}
5. จัดระยะด้วย gap และกำหนดแถว
คุณสมบัติ `gap` ใช้กำหนดระยะห่างระหว่างรายการโดยไม่ต้องเพิ่ม margin ให้ลูกทุกชิ้น สามารถระบุค่าเดียวสำหรับทั้งสองทิศทาง หรือใช้ `row-gap` และ `column-gap` แยกกันได้ ส่วน `grid-template-rows` ใช้กำหนดขนาดแถวที่ต้องการอย่างชัดเจน หากจำนวนเนื้อหาเปลี่ยนไปบ่อย `grid-auto-rows` จะช่วยกำหนดขนาดของแถวที่เบราว์เซอร์สร้างเพิ่มอัตโนมัติ
.dashboard {
display: grid;
grid-template-columns: 240px minmax(0, 1fr);
grid-template-rows: auto 1fr auto;
column-gap: 24px;
row-gap: 16px;
}
.gallery {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
row-gap: 24px;
column-gap: 16px;
}
.gallery-item {
min-width: 0;
overflow-wrap: anywhere;
}
6. วางองค์ประกอบด้วย grid-column และ grid-row
นอกจากการวางรายการตามลำดับปกติแล้ว เรายังสั่งให้รายการกินพื้นที่หลายคอลัมน์หรือหลายแถวได้ เช่น `grid-column: span 2;` หมายถึงให้องค์ประกอบครอบคลุมสองคอลัมน์ ส่วน `grid-row: span 2;` หมายถึงครอบคลุมสองแถว ควรใช้เมื่อมีเหตุผลด้านโครงสร้างหรือการเน้นเนื้อหา และตรวจสอบการแสดงผลบนหน้าจอแคบด้วยเสมอ
.feature-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
.feature-card:first-child {
grid-column: span 2;
grid-row: span 2;
}
@media (max-width: 640px) {
.feature-grid { grid-template-columns: 1fr; }
.feature-card:first-child {
grid-column: auto;
grid-row: auto;
}
}
7. สร้างโครงหน้าเว็บด้วย grid-template-areas
`grid-template-areas` ช่วยตั้งชื่อพื้นที่ในเลย์เอาต์ ทำให้มองภาพรวมได้ง่าย เช่น header, sidebar, main และ footer ชื่อเดียวกันที่ปรากฏติดกันจะรวมเป็นพื้นที่เดียวกัน หากใช้จุด (`.`) จะหมายถึงช่องที่ไม่ได้กำหนดชื่อ พื้นที่ชื่อช่วยให้โค้ดอ่านง่าย แต่ไม่ได้เปลี่ยนลำดับการอ่านของเอกสาร HTML ดังนั้นควรวาง HTML ให้มีลำดับที่เหมาะสมต่อการอ่านและเทคโนโลยีช่วยเหลือด้วย
.page {
display: grid;
grid-template-columns: 240px minmax(0, 1fr);
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 16px;
}
.site-header { grid-area: header; }
.site-sidebar { grid-area: sidebar; }
.site-main { grid-area: main; }
.site-footer { grid-area: footer; }
@media (max-width: 700px) {
.page {
grid-template-columns: minmax(0, 1fr);
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
}
}
8. จัดแนวรายการภายในกริด
คุณสมบัติ `justify-items` ใช้จัดแนวรายการตามแกนแนวนอนของเซลล์กริด ส่วน `align-items` ใช้จัดแนวตามแกนแนวตั้ง และ `place-items` เป็นทางลัดที่รวมสองคุณสมบัตินี้ไว้ด้วยกัน สำหรับการจัดแนวกริดทั้งชุดภายในพื้นที่ว่าง สามารถใช้ `justify-content` และ `align-content` ได้ ทั้งนี้การจัดแนวจะเห็นผลชัดเมื่อมีพื้นที่เหลือให้จัดสรร
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
justify-items: stretch;
align-items: center;
}
.grid-item {
min-width: 0;
padding: 20px;
}
/* ทางลัดสำหรับกำหนดทั้งสองแกน */
.grid-centered {
display: grid;
place-items: center;
}
9. ตัวอย่างโปรเจกต์: สร้างหน้าแสดงการ์ดคอร์สแบบ Responsive
ตัวอย่างต่อไปนี้เป็นหน้า HTML เต็มรูปแบบที่สามารถบันทึกเป็น `index.html` แล้วเปิดในเบราว์เซอร์ได้ทันที ใช้ CSS Grid สร้างการ์ดคอร์สที่ปรับจำนวนคอลัมน์ตามพื้นที่จริง มีป้ายระดับบทเรียน ปุ่มดูรายละเอียด และตัวอย่างเลย์เอาต์ที่ปรับสำหรับมือถือ โดยไม่ต้องติดตั้งไลบรารีภายนอก
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="ตัวอย่างหน้าแสดงคอร์สเรียนด้วย CSS Grid">
<title>ศูนย์รวมคอร์สเรียน</title>
<style>
:root {
color-scheme: light;
--page-bg: #f1f5f9;
--surface: #ffffff;
--text: #172033;
--muted: #526176;
--border: #dbe3ee;
--primary: #1d4ed8;
--primary-hover: #1e40af;
--badge-bg: #dbeafe;
--badge-text: #1e40af;
--radius: 16px;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
background: var(--page-bg);
color: var(--text);
line-height: 1.6;
}
.site-header {
padding: 28px 20px;
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.header-inner, main, .site-footer {
width: min(1120px, calc(100% - 32px));
margin-inline: auto;
}
.header-inner {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 16px;
}
h1 { margin: 0; font-size: clamp(1.5rem, 3vw, 2.2rem); }
.intro { max-width: 680px; margin: 8px 0 0; color: var(--muted); }
.theme-button {
padding: 10px 14px;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--surface);
color: var(--text);
font: inherit;
font-weight: 700;
cursor: pointer;
}
.theme-button:focus-visible, .course-link:focus-visible {
outline: 3px solid #f59e0b;
outline-offset: 3px;
}
main { padding-block: 28px 40px; }
.section-heading {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: end;
gap: 12px;
margin-bottom: 18px;
}
.section-heading h2 { margin: 0; font-size: 1.4rem; }
.section-heading p { margin: 0; color: var(--muted); }
.course-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 245px), 1fr));
gap: 18px;
align-items: stretch;
}
.course-card {
display: flex;
flex-direction: column;
min-width: 0;
padding: 20px;
border: 1px solid var(--border);
border-radius: var(--radius);
background: var(--surface);
box-shadow: 0 5px 18px rgb(15 23 42 / 5%);
}
.course-card h3 { margin: 14px 0 8px; font-size: 1.12rem; }
.course-card p { margin: 0 0 16px; color: var(--muted); }
.course-badge {
align-self: flex-start;
padding: 4px 9px;
border-radius: 999px;
background: var(--badge-bg);
color: var(--badge-text);
font-size: .8rem;
font-weight: 700;
}
.course-meta {
display: flex;
flex-wrap: wrap;
gap: 8px 12px;
margin-top: auto;
padding-top: 14px;
border-top: 1px solid var(--border);
color: var(--muted);
font-size: .9rem;
}
.course-link {
display: inline-block;
margin-top: 16px;
padding: 10px 14px;
border-radius: 10px;
background: var(--primary);
color: #fff;
text-align: center;
text-decoration: none;
font-weight: 700;
}
.course-link:hover { background: var(--primary-hover); }
.site-footer { padding-block: 0 28px; color: var(--muted); font-size: .9rem; }
html[data-theme="dark"] {
color-scheme: dark;
--page-bg: #0f172a;
--surface: #1e293b;
--text: #f1f5f9;
--muted: #c0ccdc;
--border: #475569;
--primary: #2563eb;
--primary-hover: #3b82f6;
--badge-bg: #1e3a8a;
--badge-text: #dbeafe;
}
@media (prefers-reduced-motion: no-preference) {
.course-card { transition: transform .18s ease, box-shadow .18s ease; }
.course-card:hover { transform: translateY(-3px); box-shadow: 0 12px 26px rgb(15 23 42 / 12%); }
}
</style>
</head>
<body>
<header class="site-header">
<div class="header-inner">
<div>
<h1>ศูนย์รวมคอร์สเรียน</h1>
<p class="intro">เลือกหัวข้อที่สนใจ แล้วเรียนรู้ทักษะใหม่ได้ตามจังหวะของคุณ</p>
</div>
<button class="theme-button" id="themeToggle" type="button" aria-pressed="false">เปลี่ยนเป็นโหมดมืด</button>
</div>
</header>
<main>
<section aria-labelledby="coursesTitle">
<div class="section-heading">
<h2 id="coursesTitle">คอร์สแนะนำ</h2>
<p>ตัวอย่างเลย์เอาต์ที่ใช้ CSS Grid</p>
</div>
<div class="course-grid">
<article class="course-card">
<span class="course-badge">เริ่มต้น</span>
<h3>HTML สำหรับผู้เริ่มต้น</h3>
<p>เรียนรู้โครงสร้างเอกสาร การสร้างหัวข้อ ลิงก์ รูปภาพ และแบบฟอร์มพื้นฐาน</p>
<div class="course-meta"><span>8 บทเรียน</span><span>พื้นฐาน</span></div>
<a class="course-link" href="#html-course">ดูรายละเอียดคอร์ส</a>
</article>
<article class="course-card">
<span class="course-badge">ออกแบบ</span>
<h3>CSS Layout และ Responsive</h3>
<p>ฝึกจัดวางองค์ประกอบด้วย Flexbox, Grid และ Media Queries สำหรับทุกหน้าจอ</p>
<div class="course-meta"><span>12 บทเรียน</span><span>ระดับกลาง</span></div>
<a class="course-link" href="#css-course">ดูรายละเอียดคอร์ส</a>
</article>
<article class="course-card">
<span class="course-badge">ลงมือทำ</span>
<h3>สร้างหน้าเว็บโปรเจกต์แรก</h3>
<p>นำความรู้มาประกอบเป็นหน้าเว็บจริง พร้อมตรวจสอบการใช้งานบนมือถือ</p>
<div class="course-meta"><span>6 บทเรียน</span><span>โปรเจกต์</span></div>
<a class="course-link" href="#project-course">ดูรายละเอียดคอร์ส</a>
</article>
<article class="course-card">
<span class="course-badge">ต่อยอด</span>
<h3>จัดการธีมด้วย CSS Variables</h3>
<p>สร้างชุดสีที่ดูแลได้ง่าย และทดลองเปลี่ยนธีมสว่างหรือธีมมืด</p>
<div class="course-meta"><span>5 บทเรียน</span><span>ระดับกลาง</span></div>
<a class="course-link" href="#theme-course">ดูรายละเอียดคอร์ส</a>
</article>
</div>
</section>
</main>
<footer class="site-footer">
<p>ตัวอย่างเพื่อการเรียนรู้ สามารถแก้ข้อความ สี ระยะห่าง และจำนวนการ์ดได้ตามต้องการ</p>
</footer>
<script>
const toggle = document.querySelector('#themeToggle');
toggle.addEventListener('click', () => {
const isDark = document.documentElement.dataset.theme !== 'dark';
document.documentElement.dataset.theme = isDark ? 'dark' : 'light';
toggle.setAttribute('aria-pressed', String(isDark));
toggle.textContent = isDark ? 'เปลี่ยนเป็นโหมดสว่าง' : 'เปลี่ยนเป็นโหมดมืด';
});
</script>
</body>
</html>
10. ตรวจสอบ Responsive และการเข้าถึง
การทำ Grid ให้ดูดีบนจอใหญ่ไม่ได้รับประกันว่าจะใช้งานได้ดีบนมือถือ ควรตรวจสอบว่าการ์ดไม่แคบจนข้อความอ่านยาก ไม่มีแถบเลื่อนแนวนอนโดยไม่จำเป็น รูปภาพไม่บิดสัดส่วน และปุ่มยังใช้งานได้ด้วยการแตะหรือคีย์บอร์ด ใช้ `minmax(0, 1fr)` กับคอลัมน์ที่ต้องยืดหยุ่น และกำหนด `min-width: 0` ให้ลูกบางประเภทเมื่อเนื้อหายาวหรือมี URL ที่ไม่ตัดบรรทัด
ระวังการใช้ Grid จัดลำดับเนื้อหาการเปลี่ยนตำแหน่งด้วย CSS ไม่ได้เปลี่ยนลำดับ DOM ที่โปรแกรมอ่านหน้าจอหรือการนำทางด้วยคีย์บอร์ดรับรู้ ควรจัดลำดับ HTML ให้สมเหตุสมผลตั้งแต่ต้น และใช้ CSS เพื่อจัดหน้าตา ไม่ใช่แก้ปัญหาโครงสร้างเนื้อหาที่ไม่ถูกต้อง
11. ปัญหาที่พบบ่อยและวิธีแก้
| ปัญหา | สาเหตุที่เป็นไปได้ | แนวทางแก้ไข |
|---|---|---|
| คอลัมน์ล้นหน้าจอ | กำหนดความกว้างตายตัวหรือเนื้อหาไม่ยอมตัดบรรทัด | ใช้ minmax(0, 1fr), min-width: 0 และตรวจสอบเนื้อหาที่ยาว |
| การ์ดมีความกว้างไม่เหมาะสม | กำหนดจำนวนคอลัมน์ตายตัวทุกขนาดหน้าจอ | ทดลอง repeat(auto-fit, minmax(220px, 1fr)) |
| พื้นที่ชื่อไม่ทำงาน | จำนวนชื่อในแต่ละแถวไม่สอดคล้องกัน | ตรวจสอบจำนวนคอลัมน์และรูปแบบ grid-template-areas |
| รายการกินพื้นที่เกินที่ต้องการ | ใช้ span โดยไม่ตรวจสอบจุดตัดของกริด | ลด span หรือปรับกฎใน media query |
| ข้อความยาวดันเลย์เอาต์ | คำยาวหรือลิงก์ไม่มีจุดตัด | ใช้ overflow-wrap: anywhere กับบริเวณที่เหมาะสม |
12. แบบฝึกหัดลงมือทำ
ลองแก้ไฟล์ `index.html` จากตัวอย่างให้เป็นหน้าแสดงสินค้าในร้านค้าออนไลน์ โดยใช้ข้อมูลสินค้าสมมติของคุณเอง แล้วทดสอบบนหน้าจอขนาดต่าง ๆ
1. เพิ่มการ์ดสินค้าอีก 4 รายการ และกำหนดชื่อ ราคา และคำอธิบายให้แตกต่างกัน\n2. เปลี่ยนความกว้างขั้นต่ำของการ์ดจาก 245px เป็น 280px แล้วสังเกตจำนวนคอลัมน์\n3. เพิ่มป้ายสถานะ เช่น สินค้าใหม่ หรือสินค้าขายดี โดยใช้สีที่อ่านง่าย\n4. เพิ่มส่วนหัวและส่วนท้ายให้มีพื้นหลังและระยะห่างสอดคล้องกัน\n5. ทดลองสร้างเลย์เอาต์ด้วย grid-template-areas สำหรับ header, sidebar, main และ footer\n6. ตรวจสอบด้วยคีย์บอร์ดว่าปุ่มและลิงก์ทุกตัวมี focus ที่มองเห็นได้\n7. ปรับธีมสีให้มีความแตกต่างเพียงพอระหว่างข้อความและพื้นหลัง
เกณฑ์ตรวจผลงานผลงานที่ดีควรแสดงการ์ดครบทุกชิ้น ไม่มีเนื้อหาล้นหน้าจอโดยไม่ตั้งใจ จำนวนคอลัมน์เปลี่ยนตามพื้นที่ได้ ปุ่มอ่านง่ายและใช้งานได้ และลำดับเนื้อหาใน HTML ยังสมเหตุสมผลเมื่อปิด CSS
13. คำถามที่พบบ่อย
CSS Grid ใช้แทน Flexbox ได้ทั้งหมดหรือไม่?
ไม่จำเป็นต้องแทนกันทั้งหมด Grid เหมาะกับโครงสร้างที่ต้องควบคุมแถวและคอลัมน์ ส่วน Flexbox เหมาะกับการจัดองค์ประกอบตามแกนเดียวเป็นหลัก เลือกตามลักษณะของงาน และสามารถใช้ร่วมกันได้
auto-fit กับ auto-fill ต่างกันอย่างไร?
ทั้งสองคำใช้สร้างจำนวนแทร็กตามพื้นที่ที่มี แต่ auto-fill พยายามคงแทร็กที่สร้างได้ไว้แม้บางแทร็กจะไม่มีรายการ ส่วน auto-fit จะยุบแทร็กว่างเพื่อให้แทร็กที่มีรายการขยายได้มากขึ้นเมื่อมีพื้นที่เหลือ พฤติกรรมที่เห็นจริงขึ้นอยู่กับขนาดแทร็กและเนื้อหา
จำเป็นต้องใช้ Media Query เมื่อใช้ CSS Grid หรือไม่?
ไม่เสมอไป กริดที่ใช้ repeat(auto-fit, minmax(...)) สามารถปรับจำนวนคอลัมน์ตามพื้นที่ได้เอง แต่ Media Query ยังมีประโยชน์เมื่อจำเป็นต้องเปลี่ยนโครงสร้าง ลำดับการนำเสนอ หรือระยะห่างในบางช่วงความกว้าง
ทำไมบางครั้งคอลัมน์จึงกว้างเกินกว่าที่กำหนด?
เนื้อหาภายในอาจมีขนาดขั้นต่ำที่ทำให้คอลัมน์ขยาย เช่น URL ยาวหรือรูปภาพที่ไม่จำกัดขนาด ลองใช้ minmax(0, 1fr), min-width: 0, max-width: 100% และ overflow-wrap: anywhere ในตำแหน่งที่เหมาะสม
14. สรุปบทเรียน EP18
CSS Grid ช่วยสร้างเลย์เอาต์สองมิติที่อ่านง่ายและดูแลรักษาได้ดี คุณได้เรียนรู้การกำหนดคอลัมน์ด้วย `grid-template-columns` การลดโค้ดซ้ำด้วย `repeat()` การกำหนดช่วงขนาดด้วย `minmax()` การจัดระยะด้วย `gap` การให้รายการกินหลายช่องด้วย `span` และการตั้งชื่อพื้นที่ด้วย `grid-template-areas` เมื่อนำไปใช้ร่วมกับการออกแบบ Responsive และการตรวจสอบการเข้าถึง คุณจะสร้างหน้าเว็บที่ยืดหยุ่นและเหมาะกับอุปกรณ์หลากหลายได้มากขึ้น
เลย์เอาต์ที่ดีไม่ได้มีไว้แค่จัดวางองค์ประกอบให้สวย แต่ช่วยให้ผู้ใช้ค้นหาและเข้าใจเนื้อหาได้ง่ายขึ้น
โปรเจกต์ท้ายบท: นำ CSS Grid ไปใช้กับเว็บไซต์ของคุณ
นำตัวอย่างไปต่อยอดเป็นหน้าแสดงสินค้า บทความ หรือแดชบอร์ดของคุณเอง เปลี่ยนเนื้อหา สี จำนวนการ์ด และขนาดคอลัมน์ แล้วทดสอบบนหน้าจอมือถือและเดสก์ท็อป การฝึกจากหน้าเว็บที่มีข้อมูลจริงจะช่วยให้เข้าใจว่าควรเลือก Grid หรือ Flexbox ในแต่ละสถานการณ์อย่างไร
เริ่มทดลองสร้างเลย์เอาต์ CSS Grid
อ่านจนถึงระยะ 500px ก่อนท้ายหน้าและอยู่ในหน้านี้อย่างน้อย 5 นาที เพื่อรับ EXP วันละครั้ง
⏳ กำลังจับเวลาอ่าน...