CSS
Box Model
box-sizing
เรียนรู้ว่า box-sizing ใช้กำหนดวิธีที่ browser คำนวณขนาดของ element — ความแตกต่างระหว่าง content-box และ border-box คือหัวใจสำคัญที่ช่วยให้คุณควบคุม width และ height ได้ตรงตามที่คาดไว้จริง
หัวข้อนี้คืออะไร
box-sizing (บ็อกซ์ไซซิง) คือ CSS property ที่บอก browser ว่าจะให้ width และ height ที่คุณกำหนดนั้น "หมายถึงอะไร" กันแน่ โดยปกติ browser จะใช้รูปแบบการคำนวณที่เรียกว่า content-box (คอนเทนต์บ็อกซ์) ซึ่งทำให้ element มักใหญ่กว่าขนาดที่คุณตั้งใจไว้ เพราะ padding และ border ถูกบวกเพิ่มออกไปด้านนอก แต่ถ้าใช้ border-box (บอร์เดอร์บ็อกซ์) width ที่คุณกำหนดจะรวม padding และ border ไว้ด้วยเลย ทำให้ขนาดที่ได้ตรงกับที่ตั้งใจจริงๆ box-sizing มีสองค่าที่ใช้งาน:
- content-box — ค่า default ของ browser: width/height กำหนดแค่ขนาด content เท่านั้น browser จะบวก padding และ border เพิ่มด้านนอกอีก
- border-box — width/height กำหนดขนาดรวมทั้งหมด รวม content + padding + border ไว้ด้วยกัน
ทำไมหัวข้อนี้จึงสำคัญ
นี่คือปัญหาที่นักพัฒนาทุกคนเจอเมื่อเริ่มเขียน CSS: คุณกำหนด width: 200px แต่พอดูในหน้าเว็บ กล่องกลับกว้างกว่า 200px — ทำไม? เพราะ browser ใช้ content-box โดย default ซึ่งหมายความว่า: - width: 200px → ขนาด content = 200px - padding: 20px ซ้าย-ขวา → บวกเพิ่ม 40px - border: 3px ซ้าย-ขวา → บวกเพิ่ม 6px - ขนาดรวมที่มองเห็น = 246px ← ไม่ใช่ 200px ที่คุณต้องการ การเข้าใจ box-sizing ช่วยให้คุณ: - คุมขนาด element ได้แม่นยำโดยไม่ต้องคำนวณเอง - วาง layout หลายคอลัมน์ได้โดยไม่เสียหาย - ลดเวลาแก้ bug layout อย่างมาก นั่นคือเหตุผลที่นักพัฒนา frontend ส่วนใหญ่ใส่บรรทัดนี้ไว้ในทุกโปรเจกต์: *, *::before, *::after { box-sizing: border-box; } การตั้งค่านี้ให้ทุก element ในหน้าเว็บใช้ border-box ตั้งแต่ต้น ทำให้ไม่ต้องกังวลเรื่องการคำนวณขนาดอีกต่อไป
ตัวอย่างจากชีวิตจริง
ลองนึกภาพกล่องพัสดุไปรษณีย์ที่คุณสั่งซื้อของออนไลน์ สมมติว่าคุณถามผู้ขายว่า "กล่องนี้ขนาดเท่าไหร่" และเขาตอบว่า "20 เซนติเมตร" คำถามคือ — เขาหมายถึงอะไร? แบบที่ 1 — content-box: "20 ซม. คือขนาดพื้นที่ใส่ของข้างใน ไม่รวมโฟมกันกระแทกและขอบกล่อง" → ขนาดจริงของกล่องทั้งใบจะใหญ่กว่า 20 ซม. เพราะต้องบวกขอบและโฟมเข้าไปด้วย แบบที่ 2 — border-box: "20 ซม. คือขนาดกล่องทั้งใบ รวมโฟมและขอบแล้ว" → คุณวางกล่องในที่ที่มีช่องกว้าง 20 ซม. พอดีได้เลย ไม่ต้องคาดเดา ในโลก CSS: - content-box = 20 ซม. คือพื้นที่ content เท่านั้น (padding และ border บวกเพิ่ม) - border-box = 20 ซม. คือขนาดรวมทุกอย่าง (padding และ border อยู่ข้างใน) คนส่วนใหญ่คิดแบบ border-box ในชีวิตจริง เพราะเราพูดถึง "ขนาดของกล่อง" ในความหมายรวม ไม่ใช่เฉพาะพื้นที่ด้านใน
แนวคิดหลักที่ต้องเข้าใจ
content-box: width = content เท่านั้น | border-box: width = content + padding + border รวมกัน
ก่อนดูโค้ด ทำความเข้าใจสูตรการคำนวณของแต่ละค่า: ── content-box (ค่า default) ── width ที่คุณกำหนด = ขนาด content เท่านั้น ขนาดรวมที่มองเห็น = width + padding-left + padding-right + border-left + border-right ตัวอย่าง: width: 200px, padding: 20px, border: 3px → ขนาดรวม = 200 + 20 + 20 + 3 + 3 = 246px ── border-box ── width ที่คุณกำหนด = ขนาดรวม content + padding + border ขนาดรวมที่มองเห็น = width (ที่คุณกำหนด) เลย ตัวอย่าง: width: 200px, padding: 20px, border: 3px → ขนาดรวม = 200px (browser จัดการ content ที่เหลือเองเป็น 200-40-6 = 154px) สรุป: border-box ทำให้ width ที่คุณพิมพ์เท่ากับขนาดที่คุณเห็นบนหน้าจอ
การทำงานทีละขั้นตอน
เมื่อ browser เจอ element ที่มี width, padding, และ border — นี่คือสิ่งที่เกิดขึ้น:
- 1. Browser อ่าน box-sizing ของ element — ถ้าไม่กำหนด ค่า default คือ content-box
- 2. ถ้าเป็น content-box: browser ใช้ width เป็นขนาด content area แล้วบวก padding ออกไปด้านนอก จากนั้นบวก border อีกชั้น — ขนาดรวมใหญ่กว่า width เสมอ
- 3. ถ้าเป็น border-box: browser ใช้ width เป็นขนาดรวมทั้งหมด แล้วลบ padding และ border ออก เพื่อหาขนาด content area จริง — ขนาดรวมเท่ากับ width ที่กำหนดเสมอ
- 4. height ทำงานเหมือน width ทุกประการ — content-box บวก padding-top/bottom และ border-top/bottom เพิ่ม, border-box รวมทุกอย่างไว้ใน height
- 5. margin ไม่ถูกรวมในทั้งสองรูปแบบ — margin อยู่นอกกล่องเสมอ ไม่ว่าจะใช้ box-sizing ค่าไหน
ตัวอย่างเชิงเทคนิค — โค้ดจริง
กล่องสองใบนี้มี width, padding, และ border เท่ากันทุกอย่าง — ต่างกันแค่ box-sizing
ทั้งสองกล่องกำหนด width: 200px เท่ากัน แต่กล่องแรก (content-box) จะมีความกว้างจริง 246px ส่วนกล่องที่สอง (border-box) จะกว้างแค่ 200px พอดี
<!-- HTML -->
<div class="box-content">content-box</div>
<div class="box-border">border-box</div>
/* CSS */
.box-content {
box-sizing: content-box; /* ค่า default */
width: 200px;
padding: 20px;
border: 3px solid #3b82f6;
background: #bfdbfe;
/* ขนาดรวมจริง = 200 + 20+20 + 3+3 = 246px */
}
.box-border {
box-sizing: border-box;
width: 200px;
padding: 20px;
border: 3px solid #22c55e;
background: #bbf7d0;
/* ขนาดรวมจริง = 200px พอดี */
}ดูความแตกต่างแบบ Interactive
ทดลองแก้ค่า padding และ border แล้วสังเกตว่ากล่องทั้งสองเปลี่ยนขนาดต่างกันอย่างไร: - กล่องบน (สีฟ้า) ใช้ content-box — ขนาดรวมจะขยายขึ้นเมื่อเพิ่ม padding/border - กล่องล่าง (สีเขียว) ใช้ border-box — ขนาดรวมคงที่ที่ 200px เสมอ
จุดที่ผู้เริ่มต้นมักสับสน
ตรวจสอบว่าคุณเข้าใจถูกต้องหรือยัง:
- ❌ คิดว่า width ที่กำหนดคือขนาดสุดท้ายเสมอ — ไม่ถูก ใน content-box (ค่า default) width คือแค่ขนาด content ไม่รวม padding และ border ถ้าต้องการให้ width คือขนาดสุดท้าย ต้องใช้ border-box
- ❌ งงว่าทำไมเพิ่ม padding แล้วกล่องใหญ่ขึ้น — เพราะ content-box บวก padding ออกด้านนอก ทำให้ขนาดรวมเพิ่มขึ้นตาม แต่ถ้าใช้ border-box การเพิ่ม padding จะทำให้ content area เล็กลงแทน ขนาดรวมยังคงที่
- ❌ คิดว่า border-box ทำให้ content หายไป — ไม่ใช่ content ยังอยู่ แค่ browser ปรับขนาด content area ให้เล็กลงเพื่อให้ขนาดรวมเท่ากับ width ที่กำหนด ถ้า padding + border รวมแล้วใหญ่กว่า width browser จะทำให้ content มีขนาด 0
- ❌ สับสนว่า margin รวมอยู่ใน border-box ไหม — ไม่รวม margin อยู่นอกกล่องเสมอ ทั้ง content-box และ border-box ไม่นับ margin เข้าไปในขนาดของกล่อง
เปรียบเทียบ content-box กับ border-box
สรุปความแตกต่างหลักในตารางเดียว:
| คุณสมบัติ | content-box | border-box |
|---|---|---|
| width/height หมายถึง | ขนาด content เท่านั้น | ขนาดรวม content + padding + border |
| ขนาดรวมที่มองเห็น | width + padding×2 + border×2 | = width ที่กำหนดเลย |
| เมื่อเพิ่ม padding | กล่องขยายใหญ่ขึ้น | content area หดลง กล่องคงขนาดเดิม |
| ค่า default | ใช่ — browser ใช้ค่านี้โดยอัตโนมัติ | ต้องกำหนดเอง |
| เหมาะสำหรับ | งาน legacy หรือกรณีพิเศษ | งาน layout ทั่วไป — แนะนำให้ใช้ |
| margin | ไม่รวม — อยู่นอกกล่องเสมอ | ไม่รวม — อยู่นอกกล่องเสมอ |
สรุปท้ายบท
จำง่ายๆ แบบนี้: "content-box = ขนาดเนื้อหาล้วน, border-box = ขนาดรวมขอบและช่องว่างด้านใน"
- box-sizing กำหนดวิธีคำนวณ width และ height ของ element
- content-box (ค่า default): width = content เท่านั้น — ขนาดรวมจริงใหญ่กว่า width ที่กำหนด
- border-box: width = รวม content + padding + border — ขนาดรวมจริงเท่ากับ width ที่กำหนดพอดี
- margin ไม่ถูกรวมในทั้งสองรูปแบบ
- แนวปฏิบัติที่นิยม: ใส่ *, *::before, *::after { box-sizing: border-box; } ในทุกโปรเจกต์
Lab 1 — ทดลองใช้ content-box
เป้าหมาย: เข้าใจว่า content-box ทำให้ขนาดรวมใหญ่กว่า width ที่กำหนด โจทย์: กล่องนี้มี width: 200px, padding: 20px, border: 3px solid #333 อยู่แล้ว เพิ่ม box-sizing: content-box ให้กับ .box เพื่อยืนยันว่าใช้โหมด content-box จริง ระบบจะตรวจ: 1. .box มี box-sizing: content-box ใน CSS 2. ขนาดรวมจริง (offsetWidth) = 246px (200 + 40 + 6) — ใหญ่กว่า width ที่กำหนด เงื่อนไข: ต้องเพิ่ม box-sizing: content-box ลงใน .box ให้ครบ
Lab 2 — เปลี่ยนเป็น border-box
เป้าหมาย: เห็นว่า border-box ทำให้ขนาดรวมเท่ากับ width ที่กำหนดพอดี โจทย์: กล่องเดิมจาก Lab 1 (width: 200px, padding: 20px, border: 3px solid #333) เปลี่ยน box-sizing เป็น border-box แล้วสังเกตว่า offsetWidth กลายเป็น 200px พอดี ระบบจะตรวจ: 1. .box มี box-sizing: border-box ใน CSS 2. computed box-sizing ใน browser = border-box 3. offsetWidth = 200px พอดี — width ที่กำหนดคือขนาดสุดท้าย เงื่อนไข: ต้องใช้ box-sizing: border-box (ไม่ใช่ content-box)
Lab 3 — ทำให้กล่องหลายใบมีขนาดเท่ากันจริง
เป้าหมาย: แก้ปัญหาจริง — ทำให้กล่องสองใบที่มี padding/border ต่างกัน มีขนาดรวมเท่ากันพอดี โจทย์: มีกล่องสองใบ - .card-a มี padding: 16px และ border: 2px - .card-b มี padding: 32px และ border: 4px ทั้งคู่กำหนด width: 300px แต่ขนาดรวมต่างกัน เพิ่ม box-sizing: border-box ให้ทั้งสองกล่อง เพื่อให้ offsetWidth = 300px เท่ากัน ระบบจะตรวจ: 1. .card-a มี box-sizing: border-box 2. .card-b มี box-sizing: border-box 3. offsetWidth ของ .card-a = 300px 4. offsetWidth ของ .card-b = 300px เงื่อนไข: ต้องเพิ่ม box-sizing: border-box ให้ทั้งสองกล่อง