ข้ามไปยังเนื้อหา

Box Model

ถ้ามี mental model อย่างเดียวที่คุณต้องจำก่อนจะเขียน CSS อีกบรรทัด นั่นคือ: ทุก HTML element คือกล่องสี่เหลี่ยม ไม่ใช่แค่บางครั้ง — แต่ทุกครั้ง ไม่ว่าจะเป็น heading, button, รูปภาพ หรือ <div> ที่มองไม่เห็น — ทั้งหมดคือกล่อง และทุกกล่องสร้างจากสี่ชั้นเหมือนกัน เรียงจากในออกนอก

คุณรู้จักชั้นเหล่านี้แล้วจาก Figma CSS แค่ตั้งชื่อให้เท่านั้นเอง

พื้นที่ชั้นในสุด ที่นี่คือที่อยู่ของข้อความ รูปภาพ หรือ element ลูก คุณควบคุมขนาดด้วย width และ height

.card {
width: 320px;
height: 200px;
}

ช่องว่างภายในกล่อง ระหว่าง content กับ border นึกถึง inner spacing ใน Figma auto-layout frame — ดัน content ออกจากขอบโดยไม่เลื่อน element เอง

.card {
padding: 2rem; /* ทั้งสี่ด้าน */
padding: 1rem 2rem; /* บน/ล่าง 1rem, ซ้าย/ขวา 2rem */
padding-top: 1rem; /* ด้านเดียว */
}

เส้นที่วาดรอบ element — เหมือน Stroke ใน Figma กำหนดความหนา สไตล์ และสี:

.card {
border: 2px solid #7C3AED; /* ความหนา สไตล์ สี */
border-radius: 12px; /* มุมโค้งมน */
}

ช่องว่างภายนอกกล่อง ผลัก element เพื่อนบ้านออกไป ส่วนนี้ไม่ใช่พื้นที่แสดงผลของ element — แต่เป็นช่องว่างล่องหนระหว่างกล่อง นึกถึง gap ระหว่าง frame ใน Figma

.card {
margin: 2rem; /* ทุกด้าน */
margin: 1rem 0; /* บน/ล่าง 1rem, ซ้าย/ขวา 0 */
margin-bottom: 1.5rem; /* ด้านเดียว */
}

เมื่อให้ค่าสองตัว — padding: 1rem 2rem — ลำดับคือ บน/ล่างก่อน ซ้าย/ขวาตาม สี่ค่าใช้เข็มนาฬิกา: บน, ขวา, ล่าง, ซ้าย

padding: 1rem 2rem 1rem 2rem; /* top right bottom left */

นี่คือจุดที่มือใหม่มักประหลาดใจ โดย default ค่า width ใน CSS วัดเฉพาะ content area ถ้าตั้ง width: 300px แล้วเพิ่ม padding: 20px และ border: 2px solid ความกว้างจริงที่แสดงในหน้าจะเป็น 344px — ไม่ใช่ 300px

นี่คือตรงข้ามกับวิธีที่ design tool ทำงาน ใน Figma ขอบ frame รวม stroke และ inner spacing อยู่แล้ว property box-sizing: border-box ทำให้ CSS ทำงานแบบเดียวกัน: width วัดจากขอบ border ถึงขอบ border — padding และ border รวมอยู่แล้ว ไม่บวกเพิ่ม

/* เพิ่มใน global styles ของทุก project */
*, *::before, *::after {
box-sizing: border-box;
}

ด้วย border-box element ที่มี width: 300px จะกว้าง 300px เสมอ ไม่ว่า padding หรือ border จะมากแค่ไหน padding และ border กิน content area แทนการขยายกล่องออกนอก คาดเดาได้ เหมือน Figma

Box model ทำงานเต็มที่เมื่อ element แสดงเป็น block property display ควบคุมสิ่งนี้:

ค่าพฤติกรรม
blockกินความกว้างทั้งหมด เรียงกันแนวตั้ง Default ของ <div>, <p>, <h1><h6>
inlineอยู่ในกระแสของข้อความ ไม่รองรับ width/height Default ของ <span>, <a>, <strong>
inline-blockอยู่ในกระแสข้อความแต่รองรับ width, height, padding และ margin เหมาะสำหรับ button และ badge

นี่คือเหตุผลที่ <div> เรียงต่อจาก element ก่อนหน้าในแนวตั้ง แต่ <span> ไม่เป็นแบบนั้น — หนึ่งคือ block อีกอันคือ inline

ลองแก้ไข CSS: เพิ่ม padding ของ .box, เปลี่ยนความหนา border หรือปรับ width ด้วย box-sizing: border-box ที่ตั้งไว้ ขอบนอกของ .box จะอยู่ที่ 320px เสมอ — content area จะหดเล็กลงเพื่อรับการเปลี่ยนแปลง

  • บอก developer ว่า “กว้าง 300px” โดยไม่ระบุว่ารวม padding/border หรือไม่
  • ลืมว่า margin สองฝั่งอาจ collapse กัน
  • ไม่คิดถึง box-sizing ตอนวัดขนาดใน Figma

Designer เห็น “กรอบสี่เหลี่ยมหนึ่งกรอบ” แต่ developer เห็นสี่ชั้นซ้อนกัน (content, padding, border, margin) ที่ต้องรวมกันให้ได้ขนาดสุดท้ายตรงกับ Figma

💡 ตัวอย่างจากของจริง

Figma’s Inspect panel แสดง padding/margin ที่ map ตรงกับ CSS box model เป๊ะ ช่วยให้ developer copy ค่าไปใช้ได้ทันที

ชั้นไหนของ box model อยู่ด้านนอกสุดของ border?
Padding ควบคุมอะไร?
`box-sizing: border-box` เปลี่ยนอะไร?
concept ใดใน Figma ใกล้เคียงกับ CSS margin มากที่สุด?