html font-size quyết định rem thế nào | Root 16px, 62.5% và lỗi scale

(Cập nhật: 19 tháng 7, 2026 ) CSS rem root font-size html font-size px accessibility
Kết luận

rem không phải hằng số 16 — nó là bội số của html font-size. Mặc định trình duyệt ≈ 16px1rem = 16px. Đổi root (62.5%, 14px, clamp) thì mọi rem nhảy theo. Muốn scale cả design system: đổi một chỗ (html). Muốn convert Figma: chia đúng root đang chạy, không chia 16 theo thói quen. Kiểm tra nhanh trên PX ↔ REM (chạy trình duyệt, đổi base tùy project).

Junior Việt paste font-size: 1.5rem vì “reviewer bảo dùng rem”. Sprint sau lead thêm html { font-size: 62.5% } copy blog cũ — toàn bộ card, gap, modal phóng to lệch Figma. Bug không nằm ở “rem xấu”, mà ở không ai chốt root.

Bài này đi sâu góc html font-size: rem tính từ đâu, 62.5% thực sự làm gì, đổi root theo breakpoint, và checklist trước khi merge token.

Ai nên đọc

  • Frontend inherit repo khách (outsourcing) không rõ root 16 hay 10
  • Ai migrate Figma px → CSS rem lần đầu
  • Team đang tranh luận “cấm px” nhưng layout border bị vỡ

rem gắn với root — không gắn với body

html { font-size: 16px; }   /* root */
body { font-size: 18px; }   /* không đổi 1rem */

.card {
  font-size: 1rem;   /* = 16px, không phải 18px */
  padding: 1.5rem;   /* = 24px theo root */
}

Định nghĩa ngắn: 1rem = 1 × computed font-size của phần tử gốc (thường html, hoặc :root tương đương trong tài liệu HTML).

Bạn viếtrem nhìn vàoHệ quả
Chỉ body { font-size }Vẫn htmlText mặc định đổi; token rem không scale theo body
html { font-size: 14px }14pxMọi 1rem = 14px
html { font-size: 62.5% }~10px nếu default 161rem ≈ 10px
User tăng font mặc định trình duyệtRoot lớn hơnrem lớn theo — điểm mạnh a11y

Vì sao mọi người nhớ “1rem = 16px”

Hầu hết browser desktop mặc định 16px cho root khi user không đổi. Công thức quen:

rem = px ÷ 16
24px → 1.5rem
14px → 0.875rem
32px → 2rem

Công thức này sai ngay khi:

  1. User đặt cỡ chữ trình duyệt 20px
  2. Project dùng html { font-size: 62.5% }
  3. Bạn set root theo media (html { font-size: 14px } trên mobile)
  4. Extension / OS accessibility đổi default

Luôn hỏi: root đang bao nhiêu px trên máy thật? DevTools → chọn html → Computed → font-size.


Ba kiểu đặt root phổ biến

Convention root font-size
Kiểu Ví dụ Khi nào hợp
A. Giữ 16 (khuyến nghị mặc định) html { font-size: 100%; } hoặc không set Tailwind, hầu hết design system 2024–2026. Token nghĩ bằng rem (1.5rem) thay vì ‘10px base’.
B. Trick 62.5% html { font-size: 62.5%; } + body { font-size: 1.6rem; } Team thích 24px → 2.4rem. Phải document; đừng trộn với Tailwind mặc định.
C. Root theo breakpoint / fluid html { font-size: clamp(14px, 2vw, 18px); } Scale cả trang bằng một nút. Test kỹ form và fixed UI.

Trick 62.5% — đúng toán, dễ cháy team

html {
  font-size: 62.5%; /* 16 × 0.625 = 10px (khi default = 16) */
}
body {
  font-size: 1.6rem; /* 16px — đọc bình thường */
}
h1 {
  font-size: 2.4rem; /* 24px — dễ nhớ */
}

Ưu: Não nghĩ “px ÷ 10”.
Nhược: Người mới mở PX ↔ REM vẫn để base 16 → convert sai cả bảng. Plugin Figma “px to rem” cũng hay giả định 16.

Quy tắc: một repo = một base. Ghi vào README design token dòng đầu: Root = 10px (62.5%) hoặc Root = 16px.

Root đổi theo media — scale toàn hệ

html { font-size: 14px; }
@media (min-width: 768px) {
  html { font-size: 16px; }
}

Mọi padding: 1rem, gap: 0.5rem, text-sm: 0.875rem nhảy cùng tỉ lệ. Đây là sức mạnh — và cũng là chỗ sticky footer / max-height modal dễ “đụng trần”. Checklist: mở form đăng ký, bảng giá, drawer mobile trước khi merge.


Công thức convert (và chỗ hay sai)

rem = px ÷ rootPx
px  = rem × rootPx

Ví dụ cùng 24px trên Figma:

Root thực tếrem đúng
16px1.5rem
10px (62.5%)2.4rem
14px≈ 1.714rem (nên làm tròn theo thang token: 1.75rem)

Sai phổ biến trong team outsourcing: designer gửi bảng “÷16”, codebase khách lại 62.5% → spacing phình ~1.6×.

Thử ngay (đổi Kích thước font chữ cơ sở cho khớp project):

🔄 Chuyển đổi px và rem ngay tại đây

px

rem

Công cụ chỉ làm phép tính local trên trình duyệt — không upload stylesheet.


Case study: “rem đúng nhưng UI lệch Figma”

Triệu chứng A — mọi thứ nhỏ hơn mock: Lead merge html { font-size: 62.5% } trong khi token/Tailwind vẫn được nghĩ như root 16. 1rem giờ ≈ 10px → spacing và chữ “xẹp” so với Figma chia ÷16.

Triệu chứng B — layout phình / scroll ngang: Ai đó set html { font-size: 18px } hoặc user tăng font mặc định; toàn bộ gap/padding rem phình theo. Nửa UI còn width: 320px cứng → cảm giác “vỡ tỉ lệ”.

Cách khoanh nhanh: DevTools → computed font-size của html. Tạm html { font-size: 16px !important; }. Nếu về đúng Figma → thủ phạm là root, không phải từng component.


Checklist trước khi ship token rem

  1. Document một root (16 / 10 / fluid) trong design-token README
  2. Convert bảng Figma với đúng base trên PX ↔ REM
  3. Border / hairline / outline quan trọng: giữ px
  4. Không đặt font-size “giả root” trên #app rồi kỳ vọng rem theo đó — rem không nhìn #app
  5. Test: default font trình duyệt lớn + zoom 150% + (nếu có) breakpoint đổi root
  6. PR ghi rõ: “Root giả định = …px”

Muốn góc khi nào chọn px vs rem vs em (border, padding nút, media query): xem thêm px vs rem trong CSS. Bài này chỉ chốt root quyết định rem thế nào.


Liên kết liên quan