CSS
Grid
auto-fit / auto-fill
เรียนรู้วิธีสร้าง responsive grid ที่ปรับจำนวนคอลัมน์อัตโนมัติตามพื้นที่ด้วย auto-fit และ auto-fill — ไม่ต้องกำหนดจำนวนคอลัมน์ตายตัว และไม่ต้องเขียน media query
หัวข้อนี้คืออะไร
auto-fit และ auto-fill คือคีย์เวิร์ดพิเศษที่ใช้แทนจำนวนคอลัมน์ใน repeat() เพื่อให้ browser คำนวณจำนวนคอลัมน์เองตามพื้นที่ที่มี มักใช้คู่กับ minmax() เสมอ ในรูปแบบ repeat(auto-fit, minmax(ขนาดขั้นต่ำ, 1fr)) ซึ่งหมายความว่าแต่ละคอลัมน์กว้างอย่างน้อยตามที่กำหนด และขยายได้เต็มพื้นที่ที่เหลือ ความต่างระหว่างสองคีย์เวิร์ด: auto-fill สงวนพื้นที่คอลัมน์ว่างแม้ไม่มี item วาง / auto-fit ยุบคอลัมน์ว่างออกและขยาย item ที่มีให้เต็มพื้นที่
- auto-fit / auto-fill ใช้แทนจำนวนคอลัมน์ตายตัวใน repeat()
- browser คำนวณจำนวนคอลัมน์เองตามพื้นที่และขนาดขั้นต่ำที่กำหนด
- ต้องใช้คู่กับ minmax() เสมอ — เช่น repeat(auto-fit, minmax(200px, 1fr))
- ไม่ต้องเขียน media query เพื่อเปลี่ยนจำนวนคอลัมน์
- auto-fit ขยาย items ที่มี / auto-fill สงวนพื้นที่คอลัมน์ว่างไว้
ทำไมหัวข้อนี้สำคัญ
repeat(3, 1fr) ทำให้กริดมี 3 คอลัมน์ตายตัวเสมอ บนมือถือที่แคบกว่าจะทำให้คอลัมน์เบียดกันจนอ่านไม่ได้ ต้องเขียน media query ซ้ำ ๆ เพื่อเปลี่ยนจำนวนคอลัมน์ทุก breakpoint auto-fit แก้ปัญหานั้นในบรรทัดเดียว browser คิดเองว่าจะใส่ได้กี่คอลัมน์โดยไม่ต้องรู้ขนาดหน้าจอล่วงหน้า
- Card grid สินค้า — 4 คอลัมน์บน desktop, 2 บน tablet, 1 บน mobile โดยอัตโนมัติ
- Photo gallery — ปรับจำนวนรูปต่อแถวตามพื้นที่โดยไม่ต้องแก้ CSS
- Team member grid — เพิ่มสมาชิกใหม่ได้โดยไม่ต้องแก้ layout
- Dashboard widget — widgets เรียงตัวตามพื้นที่ที่มีให้
- ลด media query ได้มาก — เขียน CSS เดียวรองรับทุกขนาดหน้าจอ
ตัวอย่างจากชีวิตจริง
ลองนึกถึงพนักงานวางรองเท้าในร้านค้า ถ้าบอกว่า "วางแถวละ 4 คู่" — ชั้นแคบก็ยังต้องฝืนวาง 4 คู่ ชั้นกว้างก็เว้นว่างเหลือเยอะ แต่ถ้าบอกว่า "แต่ละคู่กว้างอย่างน้อย 20 ซม. วางให้เต็มชั้น" — พนักงานจะคิดเองว่าใส่ได้กี่คู่และปรับให้พอดีทุกครั้ง auto-fit ทำงานแบบเดียวกัน คุณบอกแค่ว่า "แต่ละคอลัมน์กว้างอย่างน้อย 200px" browser คิดเองว่าจะใส่ได้กี่คอลัมน์และปรับให้พอดีเสมอ
แนวคิดหลักที่ต้องเข้าใจ
มีสามส่วนที่ต้องเข้าใจก่อน: ① minmax(min, max) กำหนดขนาดขั้นต่ำและขั้นสูงของแต่ละคอลัมน์ minmax(200px, 1fr) = กว้างอย่างน้อย 200px แต่ขยายได้ถึง 1fr ถ้ามีพื้นที่ ② auto-fill "เติมคอลัมน์ให้เต็มพื้นที่" — สร้างคอลัมน์ตามจำนวนที่ใส่ได้ในพื้นที่นั้น แม้ไม่มี item วางอยู่ container กว้าง 600px + minmax(200px, 1fr) → 3 คอลัมน์เสมอ แม้มี item แค่ 1 ชิ้น พื้นที่ที่เหลือยังถูกจองเป็นคอลัมน์ว่าง ③ auto-fit "ยุบคอลัมน์ว่างออก" — สร้างคอลัมน์เฉพาะตำแหน่งที่มี item จริง ๆ container กว้าง 600px + minmax(200px, 1fr) + 2 items → 2 item ขยายเต็ม 600px ไม่มีคอลัมน์ว่างเหลือ กฎจำง่าย: auto-fill สงวนพื้นที่ / auto-fit ขยาย items
การทำงานทีละขั้นตอน
นี่คือขั้นตอนการสร้าง responsive grid ด้วย auto-fit:
- 1. กำหนด display: grid ที่ container — เปิด grid context ก่อนเสมอ
- 2. ใช้ repeat(auto-fit, ...) ใน grid-template-columns — แทนการระบุจำนวนคอลัมน์ตายตัว
- 3. กำหนด minmax(ขนาดขั้นต่ำ, 1fr) — เช่น minmax(200px, 1fr) หมายความว่าแต่ละคอลัมน์กว้างอย่างน้อย 200px
- 4. browser คำนวณจำนวนคอลัมน์เอง — container กว้าง 650px กับ minmax(200px, 1fr) ได้ 3 คอลัมน์ / 400px ได้ 2 คอลัมน์
- 5. เพิ่ม gap ตามต้องการ — layout พร้อมใช้งานบนทุกขนาดหน้าจอโดยไม่ต้องเขียน media query
ตัวอย่างเชิงเทคนิค / โค้ด
สองรูปแบบที่ใช้บ่อยที่สุด: repeat(auto-fit, minmax(200px, 1fr)) → items ขยายเต็มพื้นที่ที่มี — เหมาะกับ card grid, product listing, gallery ทั่วไป repeat(auto-fill, minmax(200px, 1fr)) → คอลัมน์ว่างถูกสงวนไว้ — เหมาะกับ grid ที่อาจมี items น้อย แต่ต้องการรักษาโครงตาราง
auto-fit และ auto-fill ต้องใช้คู่กับ minmax() เสมอ — ต่างกันตรงพฤติกรรมเมื่อ items ไม่เต็มแถว
/* ✅ auto-fit — items ขยายเต็มพื้นที่ */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
/* ✅ auto-fill — สงวนพื้นที่คอลัมน์ว่าง */
.card-grid-fill {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
}
/* ❌ ใช้ auto-fit โดยไม่มี minmax() — browser ไม่รู้ขนาดขั้นต่ำ */
.wrong {
display: grid;
grid-template-columns: repeat(auto-fit, 1fr); /* ใช้ไม่ได้ */
}จุดที่ผู้เริ่มต้นมักสับสน
- ❌ ใช้ auto-fit โดยไม่มี minmax() — เช่น repeat(auto-fit, 1fr) — browser ไม่รู้ขนาดขั้นต่ำของคอลัมน์ ผลลัพธ์จะไม่แน่นอน ต้องใช้ minmax() เสมอ
- ❌ คิดว่า auto-fit กับ auto-fill ต่างกันมาก — ความต่างเห็นได้ชัดเฉพาะตอนที่ items ไม่เต็มแถว ถ้า items เต็มทุกคอลัมน์ ทั้งสองให้ผลเหมือนกัน
- ❌ ลืม 1fr ใน minmax() — minmax(200px, 200px) ทำให้คอลัมน์กว้าง 200px ตลอด ไม่ยืดตามพื้นที่ ต้องใส่ 1fr เป็นค่าสูงสุดเพื่อให้ยืดเต็มพื้นที่ที่เหลือ
- ❌ ตั้งขนาดขั้นต่ำใหญ่เกินไป — minmax(500px, 1fr) บนมือถือกว้าง 375px จะได้ 0 คอลัมน์และเกิด overflow ให้ใช้ขนาดที่สมเหตุสมผล เช่น 150px–280px
เปรียบเทียบกับสิ่งที่ใกล้เคียง
สรุปความแตกต่างระหว่างวิธีกำหนดคอลัมน์ใน grid-template-columns:
| วิธี | ตัวอย่าง | จำนวนคอลัมน์ | เหมาะกับ |
|---|---|---|---|
| ตายตัว | repeat(3, 1fr) | 3 เสมอ | layout ที่ต้องการคอลัมน์แน่นอน เช่น sidebar + main |
| auto-fill | repeat(auto-fill, minmax(200px, 1fr)) | ปรับตามพื้นที่ สงวนคอลัมน์ว่าง | grid ที่อาจมี items น้อย แต่ต้องรักษาโครงตาราง |
| auto-fit | repeat(auto-fit, minmax(200px, 1fr)) | ปรับตามพื้นที่ ขยาย items | card grid, gallery, product listing ทั่วไป |
| ผสม px + fr | 240px 1fr | ตายตัว 2 คอลัมน์ | sidebar ความกว้างตายตัว + main content ยืดหยุ่น |
สรุปท้ายบทแบบจำง่าย
auto-fit ขยาย items ที่มีให้เต็มพื้นที่ / auto-fill สงวนพื้นที่คอลัมน์ว่างไว้ ถ้าไม่แน่ใจให้เลือก auto-fit — เหมาะกับ card grid ทั่วไปมากกว่า
- repeat(auto-fit, minmax(200px, 1fr)) — สูตรมาตรฐานสำหรับ responsive card grid
- auto-fit = ไม่มีคอลัมน์ว่าง items ที่มีขยายเต็มพื้นที่
- auto-fill = สงวนคอลัมน์ว่างไว้ items ไม่ขยายเกิน minmax
- minmax(min, max) กำหนดขนาดขั้นต่ำ–สูงสุดของคอลัมน์
- ต้องใช้ minmax() คู่กับ auto-fit / auto-fill เสมอ
- ไม่ต้องเขียน media query — browser ปรับจำนวนคอลัมน์เองตามพื้นที่
Lab 1: สร้าง Card Grid ด้วย auto-fit
โจทย์: เพิ่ม display: grid และ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)) ให้ .card-grid
Lab 2: เปรียบเทียบ auto-fit กับ auto-fill
โจทย์: เพิ่ม display: grid และ grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)) ให้ .grid-b แล้วสังเกตว่าต่างจาก .grid-a (auto-fit) อย่างไร
Lab 3: สร้าง Responsive Grid โดยไม่กำหนดคอลัมน์ตายตัว
โจทย์: สร้าง responsive product grid ด้วย auto-fit และ minmax(180px, 1fr) ที่ปรับจำนวนคอลัมน์เองตามพื้นที่