px vs rem trong CSS | Root 16px, trick 62.5% và khi nào dùng px cho border
Font + spacing → rem. Border / hairline / “đúng 1 pixel thiết bị” → px. Root mặc định 16px (1rem = 16px). Trick 62.5% chỉ khi team chấp nhận 1rem ≈ 10px và không trộn với Tailwind mặc định. Trước khi migrate token: lập bảng px→rem bằng PX ↔ REM, rồi test zoom chữ trình duyệt — đó là lý do chọn rem.
Figma ghi 24. Junior viết font-size: 24px. Reviewer bảo “dùng rem”. Intern chia 16 → 1.5rem — đúng. Sprint sau ai đó set html { font-size: 62.5% } copy từ blog 2018 → toàn bộ spacing nhảy, QA báo “letter-spacing như bug”.
Dev VN trong team outsourcing thường inherit repo khách (Mix 62.5% + Tailwind text-base = 1rem). Bài này chốt quy ước, a11y zoom, và bảng convert trước migrate.
Bài viết này giúp bạn
- Hiểu root 16 vs 62.5%
- Biết khi nào px vẫn đúng
- Phân biệt rem / em / px
- Convert bảng token trước khi đụng codebase
- Checklist accessibility zoom
px và rem khác nhau ở điểm nào?
| px | rem | |
|---|---|---|
| Bản chất | Đơn vị CSS “tuyệt đối” theo reference pixel | Tương đối theo font-size của html |
| User tăng cỡ chữ mặc định | Nhiều chỗ không theo (nếu mọi thứ px) | Font/spacing rem scale theo |
| Đọc design | Trùng số Figma | Cần chia cho root |
| Border 1px | Ổn định | Có thể dày/mỏng lạ khi root đổi |
/* Khuyến nghị hiện đại */
html {
font-size: 100%; /* tôn trọng default user — thường 16px */
}
.title {
font-size: 1.5rem; /* 24px khi root 16 */
margin-bottom: 1rem;
border-bottom: 1px solid #e5e7eb; /* border: px */
}
| Thuộc tính | Ưu tiên | Lý do |
|---|---|---|
| font-size, line-height (nhiều case) | rem | Theo root + user preference |
| padding, margin, gap | rem | UI scale đồng bộ với chữ |
| border-width, outline | px | Hairline ổn định |
| box-shadow offset nhỏ | px (thường) | Tránh bóng ‘phình’ khi zoom text |
| media query breakpoint | px hoặc em (tùy team) | Nhiều design system vẫn chốt px viewport |
Root 16px vs trick 62.5%
Root 16 (mặc định trình duyệt)
24px → 24 / 16 = 1.5rem
32px → 2rem
8px → 0.5rem
Tailwind, nhiều UI kit, và MDN examples giả định thế giới này. Ưu tiên cho project mới.
Trick 62.5%
html {
font-size: 62.5%; /* 16 × 0.625 = 10px nếu default user = 16 */
}
body {
font-size: 1.6rem; /* lại về ~16px cho body */
}
.heading {
font-size: 2.4rem; /* “như” 24px — chia 10 dễ */
}
Ưu: tính nhẩm nhanh kiểu cũ.
Nhược: thư viện giả định 1rem=16 sẽ sai tỷ lệ; user đổi default font → 62.5% của default mới, không còn đúng “10px thần thánh”; onboarding member mới dễ nhầm.
Quy tắc: một repo một convention. Có 62.5% thì ghi README + comment trên html. Không thì đừng thêm.
Accessibility: zoom chữ ≠ zoom trang
Người dùng (và nhiều chuẩn a11y) tăng cỡ chữ mặc định trình duyệt. Nếu toàn bộ UI là px, layout có thể:
- Chữ lớn nhưng nút/padding vẫn nhỏ → chạm khó
- Hoặc chữ bị cắt trong hộp cố định px
Với rem, tăng root kéo theo spacing — form login / nav thường chịu đựng tốt hơn. Test bắt buộc: Firefox/Chrome → cỡ chữ 150–200%, mở trang có input tiếng Việt (dấu thanh), xem có đứt layout không.
Ctrl + zoom cả trang khác với đổi default font — cả hai nên thử; rem giúp nhiều hơn với default font.
Bảng convert trước khi migrate design token
Đừng đổi từng class trong PR 400 file. Làm bảng:
| Figma (px) | rem @16 | rem @10 (62.5%) |
|---|---|---|
| 4 | 0.25 | 0.4 |
| 8 | 0.5 | 0.8 |
| 12 | 0.75 | 1.2 |
| 16 | 1 | 1.6 |
| 24 | 1.5 | 2.4 |
| 32 | 2 | 3.2 |
| 48 | 3 | 4.8 |
Dán từng cột vào Chuyển PX ↔ REM: chỉnh base size 16 hoặc 10, nhập px, lấy rem. Export token JSON/--space-* một lần.
🔄 Chuyển đổi px và rem ngay tại đây
Khi khách đổi “design system từ 8pt sang 4pt grid”, chỉ cần cập nhật bảng + regenerate — không cãi nhau trên PR từng margin: 13px.
Case study
Repo khách: Tailwind + html { font-size: 62.5% }
text-base (1rem) thành ~10px → chữ toàn site như caption. Fix: xóa 62.5% hoặc custom Tailwind fontSize theo root thật. Không được giữ cả hai im lặng.
Migrate token agency
80 giá trị spacing px trong SCSS. Team chốt root 16, chạy bảng qua tool, thay $space-24: 24px → $space-24: 1.5rem, giữ $border-hairline: 1px. Test zoom 200% trên checkout — nút không còn dính nhau.
Checklist
- Convention root đã ghi (16 vs 62.5%)
- Font/spacing → rem
- Border hairline → px
- Không trộn em lồng nhau không kiểm soát
- Bảng convert đã review với design
- Zoom chữ 150%+ trên form chính
- Lib UI (Tailwind/MUI) khớp giả định rem
Liên quan
- Chuyển PX ↔ REM — đổi base, convert nhanh
- Fluid type (
clamp) — bước sau khi đã ổn rem - Contrast chữ — a11y không chỉ là đơn vị
Bookmark lý do: một chỗ chốt 16 vs 62.5%, px cho border, và quy trình bảng convert token trước khi đụng PR lớn.