อธิบายหน่วยวัด CSS: px, rem, em, vh — และควรใช้ตอนไหน
การเลือกหน่วยวัด CSS ผิดอาจทำให้ Layout พังเมื่อเปลี่ยนขนาดหน้าจอ ตัวอักษรไม่ปรับตามความต้องการของผู้ใช้งาน และระยะห่างที่ดูไม่สม่ำเสมอ นี่คือคู่มือเชิงปฏิบัติเพื่อช่วยให้คุณเลือกหน่วยที่ถูกต้องได้ทุกครั้ง
ทำไมหน่วย CSS ถึงสำคัญ
CSS มีหน่วยวัดความยาวมากกว่าสิบรายการ แต่ในทางปฏิบัติเหล่านักพัฒนามักใช้กันห้าอย่างหลักๆ คือ px, rem, em, % และหน่วย viewport อย่าง vh และ vw การเลือกผิดไม่ใช่เรื่องที่เห็นชัดเสมอไป — เลย์เอาต์อาจจะดูดีบนหน้าจอของคุณแต่พังเมื่ออยู่บนหน้าจอของคนอื่น หรือผ่านการตรวจสอบ visual QA แต่ไม่ผ่านการตรวจสอบ accessibility เพราะมันละเลยความชอบของผู้ใช้ในการตั้งค่าขนาดตัวอักษรในเบราว์เซอร์
คู่มือนี้จะอธิบายว่าแต่ละหน่วยวัดอะไรจริงๆ ให้กฎการตัดสินใจที่เป็นรูปธรรมสำหรับแต่ละสถานการณ์ และครอบคลุมข้อผิดพลาดที่เกิดขึ้นซ้ำแล้วซ้ำเล่าในการรีวิวโค้ด
px — Absolute Pixels
หนึ่งหน่วย px ใน CSS จะเทียบเท่ากับหนึ่ง device-independent pixel ไม่ใช่พิกเซลบนหน้าจอจริงเสมอไป บนหน้าจอ retina 2x หนึ่งหน่วย CSS px จะถูกแสดงผลโดยใช้ 2 พิกเซลทางกายภาพ นี่หมายความว่า px มีขนาดที่สม่ำเสมอกันในแง่ของขนาดการมองเห็น แต่เป็นแบบ absolute — มันจะไม่ปรับขนาด (scale) ไปตามอะไรเลย
เมื่อไหร่ควรใช้ px:
- เส้นขอบ:
border: 1px solid— เส้นขอบขนาด 1px ควรจะดูเหมือนเส้นบางๆ เสมอ ไม่ว่าจะอยู่ในบริบทใด - เงาของกล่องและเส้นขอบ (Outlines): รายละเอียดความแม่นยำที่ไม่ควรปรับขนาดตาม
- จุดตัด Media query:
@media (min-width: 768px) - องค์ประกอบตกแต่งที่มีขนาดคงที่ (ไอคอนที่มีขนาดแน่นอน, เส้นแบ่งส่วน)
เมื่อไม่ควรใช้ px: ขนาดตัวอักษร, padding และ margin ผู้ใช้งานที่ตั้งค่าขนาดตัวอักษรในเบราว์เซอร์เป็น 20px เพราะพวกเขามีปัญหาในการอ่านข้อความขนาดเล็ก จะไม่ได้รับประโยชน์จากเลย์เอาต์ของคุณเลยหากทุกอย่างถูกกำหนดตายตัวในหน่วย px ความต้องการของพวกเขาจะถูกละเลยโดยสิ้นเชิง
rem — Root Em
rem ย่อมาจาก "root em" มันจะอ้างอิงกับ font-size ขององค์ประกอบ html เสมอ ไม่ใช่ขององค์ประกอบแม่ สิ่งนี้ทำให้มันคาดการณ์ผลลัพธ์ได้ในแบบที่ em ทำไม่ได้
โดยปกติแล้ว เบราว์เซอร์ส่วนใหญ่จะตั้งค่า root font size ไว้ที่ 16px ดังนั้น:
1rem = 16px | 1.5rem = 24px | 0.875rem = 14px
เมื่อไหร่ควรใช้ rem:
- ขนาดตัวอักษร — rem จะเคารพการตั้งค่าขนาดตัวอักษรของเบราว์เซอร์ผู้ใช้
- ระยะห่างที่ควรปรับขนาดอย่างสม่ำเสมอพร้อมกับขนาดตัวอักษร (padding, margin, gap)
- การกำหนดขนาดคอมโพเนนต์เมื่อคุณต้องการให้ทุกอย่างขยายขนาดไปพร้อมกัน
เทคนิค 62.5%: นักพัฒนาบางคนตั้งค่า html { font-size: 62.5%; } เพื่อให้ 1rem เท่ากับ 10px (เนื่องจาก 62.5% ของ 16px = 10px) สิ่งนี้ช่วยลดความยุ่งยากในการคำนวณในใจ: <1.4rem = 14px> ข้อเสียคือมันจะไปทับความชอบพื้นฐานของผู้ออกแบบ เว้นแต่คุณจะใช้อย่างระมัดระวัง — ให้ทำเฉพาะเมื่อคุณเข้าใจผลกระทบด้าน accessibility และมีการกำหนดค่าใหม่ในระดับคอมโพเนนต์เท่านั้น
em — Relative to Parent
<em จะอ้างอิงกับ computed font-size ขององค์ประกอบปัจจุบัน (หรือขององค์ประกอบแม่ เมื่อนำไปใช้กับ font-size เอง) สิ่งนี้ทำให้มันมีประโยชน์สำหรับคอมโพเนนต์ที่ต้องการปรับขนาดตามสัดส่วนของขนาดตัวอักษรของตัวเอง
กรณีการใช้งานมาตรฐาน: button padding หากคุณเขียน <padding: 0.5em 1em ระยะห่างของปุ่มจะปรับขนาดโดยอัตโนมัติเมื่อคุณเปลี่ยน font-size ของปุ่ม — ปุ่มขนาดเล็กจะได้ padding ที่เล็กลง ปุ่มขนาดใหญ่จะได้ padding มากขึ้น
.btn { font-size: 1rem; padding: 0.5em 1em; }
.btn-lg { font-size: 1.25rem; /* padding scales automatically */ }
ปัญหาการคำนวณซ้อนทับ (Compounding problem): เมื่อคุณซ้อนองค์ประกอบที่มีขนาดตัวอักษรเป็น em พวกมันจะคูณกัน การตั้งค่าบรรพบุรุษที่ <1.2em และลูกที่ <1.2em จะทำให้ลูกมีขนาดสุทธิเท่ากับ <1.44em นี่คือเหตุผลว่าทำไม rem จึงถูกแนะนำสำหรับขนาดตัวอักษรในกรณีส่วนใหญ่ — เพราะ rem อ้างอิงถึง root เสมอ การซ้อนกันจึงไม่ทำให้เกิดการคูณซ้ำ
เมื่อไหร่ควรใช้ em: padding, margin และ line-height บนคอมโพเนนต์ที่คุณต้องการให้ขนาดติดตามกับ font-size ของคอมโพเนนต์นั้นเอง หลีกเลี่ยงการใช้ em สำหรับ font-size ในคอมโพเนนต์ที่ซ้อนกัน
% — Percentage
Percentage จะอ้างอิงกับ มิติที่สอดคล้องกันขององค์ประกอบแม่ เสมอ เปอร์เซ็นต์ความกว้างจะอ้างอิงจากความกว้างของแม่; เปอร์เซ็นต์ความสูงจะอ้างอิงจากความสูงของแม่ (โดยมีข้อจำกัดบางประการ)
มันจะมีประโยชน์เป็นพิเศษสำหรับ Fluid layouts: <width: 100% หมายถึง "ใช้พื้นที่ความกว้างที่มีทั้งหมด" เมื่อใช้ร่วมกับ max-width มันจะสร้างคอนเทนเนอร์แบบ Responsive:
.container { width: 100%; max-width: 1200px; margin: 0 auto; }
สำหรับ font-size การใช้เปอร์เซ็นต์จะทำงานเหมือน em — มันจะคูณกับค่าขององค์ประกอบแม่ ให้ใช้ rem แทนเพื่อผลลัพธ์ที่คาดการณ์ได้มากกว่า
vh, vw — Viewport Units
<1vh = 1% ของความสูงของ viewport. <1vw = 1% ของความกว้างของ viewport สิ่งเหล่านี้ไม่ขึ้นกับองค์ประกอบใดๆ — พวกมันจะอ้างอิงถึงขนาดหน้าต่างเบราว์เซอร์เสมอ
เมื่อไหร่ควรใช้ viewport units:
- Full-screen sections: <
height: 100vhสำหรับส่วน Hero ที่ต้องการให้เต็มหน้าจอพอดี - Fluid typography: <
font-size: clamp(1rem, 2.5vw, 2rem)สำหรับข้อความที่ปรับขนาดอย่างราบรื่นระหว่างขนาดหน้าจอโดยไม่ต้องใช้ media queries - Full-width images or videos: <
width: 100vwเพื่อให้ภาพหรือวิดีโอหลุดออกจากคอนเทนเนอร์
ปัญหาแถบเครื่องมือบนเบราว์เซอร์มือถือ:** ในเบราว์เซอร์มือถือ แถบที่อยู่ (address bar) จะปรากฏและหายไปเมื่อคุณเลื่อนหน้าจอ ซึ่งจะทำให้ความสูงของ viewport เปลี่ยนไป <100vh อาจทำให้เนื้อหาถูกตัดขาดหรือสร้างแถบการเลื่อนขึ้นมา CSS จึงมีการเพิ่ม <dvh (dynamic viewport height), <svh (small — เห็นแถบที่อยู่), และ <lvh (large — ซ่อนแถบที่อยู่) เพื่อจัดการกับปัญหานี้ การรองรับเบราว์เซอร์สำหรับ dvh นั้นใช้งานได้ดีในปี 2024+ ให้ใช้ <height: 100dvh สำหรับเลย์เอาต์เต็มหน้าจอในมือถือ
คู่มือการตัดสินใจเลือกหน่วย CSS
| สิ่งที่ต้องการกำหนดขนาด | ใช้ตัวนี้ | เหตุผล |
|---|---|---|
| Body / ขนาดตัวอักษรหลัก | rem | เคารพความชอบของผู้ใช้, ไม่เกิดการคูณซ้อน |
| ขนาดตัวอักษรในคอมโพเนนต์ | rem | สม่ำเสมอ, คาดการณ์ได้ |
| Padding / Margin ของคอมโพเนนต์ | em หรือ <rem> | em หากต้องการให้ติดตามขนาดตัวอักษร; rem เพื่อความสม่ำเสมอ |
| เส้นขอบ, เงาของกล่อง | px | ไม่ควรปรับขนาดตามเลย |
| จุดตัด Media query | px หรือ <em> | px เพื่อความง่าย; em เพื่อให้จุดตัดปรับตามการตั้งค่าตัวอักษรของผู้ใช้ |
| ความกว้างคอนเทนเนอร์แบบ Fluid | % + <max-width> | ใช้พื้นที่ว่างที่มี, จำกัดที่ขนาดสูงสุด |
| ส่วน Hero ความสูงเต็มจอ | <100dvh | คำนึงถึงแถบเครื่องมือของเบราว์เซอร์ในมือถือ |
| Fluid typography | <clamp() พร้อม rem + vw | ปรับขนาดอย่างราบรื่นระหว่างจุดตัดต่างๆ |
ข้อผิดพลาดที่พบบ่อยที่สุด
1. การใช้ px สำหรับทุกขนาดตัวอักษร สิ่งนี้ทำลายการเข้าถึง (accessibility) ผู้ใช้ที่เพิ่มขนาดพื้นฐานของตัวอักษรในเบราว์เซอร์จะพบว่าข้อความของคุณไม่เปลี่ยนแปลง ให้ใช้ rem สำหรับขนาดตัวอักษรเพื่อให้ UI เคารพความชอบนั้น
2. การใช้ em สำหรับขนาดตัวอักษรในคอมโพเนนต์ที่ซ้อนกัน ปัญหาการคำนวณซ้อนทับจะเกิดขึ้นที่นี่ เมนูภายในคาร์ดภายในโมดอลอาจจบลงด้วยการคูณสะสมถึง 3 เท่า ให้ใช้ rem สำหรับขนาดตัวอักษรแทน
3. การใช้ vh สำหรับเลย์เอาต์เต็มจอโดยไม่มี dvh fallback บนมือถือ แถบที่อยู่ทำให้เกิดการขยับของเลย์เอาต์ (layout shifts) ให้ใช้ <min-height: 100svh หรือ <height: 100dvh> แทน
4. การลืมว่าความสูง % จำเป็นต้องมีองค์ประกอบแม่ที่มีการระบุความสูงชัดเจน <height: 100% บนลูกจะไม่มีผลเลยหากพ่อมี <height: auto> ให้ใช้ <vh> หรือ Flexbox แทน
สูตรแปลงจาก px → rem
ขนาดตัวอักษรพื้นฐานปกติคือ 16px สูตรสำหรับการแปลงคือ:
ตัวอย่าง: <
24px ÷ 16 = 1.5rem
หากคุณทำงานกับเครื่องมือออกแบบที่ส่งออกเป็นพิกเซล เครื่องมือ PX to REM Converter ของเราจะจัดการการคำนวณให้ทันที เพียงวางค่า px ใดๆ (หรือรายการของค่าต่างๆ) และรับค่า rem ที่เท่ากัน พร้อมรองรับการกำหนดขนาดพื้นฐานเอง
แปลง px เป็น rem ทันที
วางค่า pixel ใดก็ได้เพื่อรับค่าที่เทียบเท่าในหน่วย rem รองรับการกำหนดขนาด Font พื้นฐานที่กำหนดเอง