Choosing the right font size unit in CSS seems simple — until you encounter px, rem, em, pt, vw, and % all in the same project. Each unit behaves differently, and using the wrong one can break your layout when users change their browser settings or view your site on different devices. This guide explains every CSS font size unit, shows you how to convert between them, and helps you decide which to use in different scenarios.
px
rem
em
pt
vw
%
CSS provides several units for specifying font sizes. They fall into two categories: absolute units (fixed size) and relative units (size relative to a reference).
Pixels are the default unit for most developers. They're simple, predictable, and don't change based on context.
h1 { font-size: 32px; } p { font-size: 16px; } small { font-size: 12px; }
The main advantage of px is predictability: 16px is always 16px regardless of nesting or inheritance. The disadvantage is that px doesn't respect the user's browser font-size setting, which can be an accessibility concern for users who need larger text.
The em unit is calculated based on the parent element's font-size. If a parent has font-size: 20px, then 1em = 20px inside that parent.
font-size: 20px
1em = 20px
/* Parent */ .card { font-size: 20px; } /* Child: 1.5 × 20px = 30px */ .card h2 { font-size: 1.5em; } /* Grandchild: 1.2 × 30px = 36px (compounding!) */ .card h2 span { font-size: 1.2em; }
The compounding behavior is the main gotcha with em. Each nesting level multiplies against its parent, which can lead to unexpectedly large or small text. This is why many developers prefer rem for font-sizes.
em is still excellent for non-font-size properties like padding, margins, and line-height, where you want values to scale with the element's own font-size:
.button { font-size: 16px; padding: 0.5em 1em; /* 8px 16px — scales with font-size */ line-height: 1.5; /* Relative to element's font-size */ }
The rem unit (root em) is always relative to the <html> element's font-size. By default, browsers set this to 16px.
<html>
/* Default: 1rem = 16px */ html { font-size: 16px; } h1 { font-size: 2rem; } /* 32px */ h2 { font-size: 1.5rem; } /* 24px */ p { font-size: 1rem; } /* 16px */ small { font-size: 0.875rem; } /* 14px */
The key advantage: rem doesn't compound. No matter how deeply nested, 1.5rem is always 24px (assuming default root size). This makes rem the preferred choice for typography in modern CSS.
1.5rem
Converting px to rem is simple: divide the pixel value by the root font-size.
rem = px ÷ root-font-size
rem = px ÷ 16
Reverse the formula to convert rem back to px:
px = rem × root-font-size
px = rem × 16
For example: 2.5rem × 16 = 40px.
2.5rem × 16 = 40px
Points are a print unit. The CSS specification defines:
px = pt × (4/3)
px = pt × 1.333
pt = px × 0.75
padding: 0.5em 1.5em
line-height: 1.5
line-height: 1.5em
border: 1px solid
CSS clamp() lets you create font sizes that scale smoothly between a minimum and maximum value:
clamp()
h1 { /* Minimum 1.75rem, preferred 5vw, maximum 3rem */ font-size: clamp(1.75rem, 5vw, 3rem); } p { /* Minimum 0.875rem, preferred 1.2vw, maximum 1.125rem */ font-size: clamp(0.875rem, 1.2vw, 1.125rem); }
Some developers set the root font-size to 62.5% (10px) to make rem math easier:
html { font-size: 62.5%; } /* 1rem = 10px */ body { font-size: 1.6rem; } /* Restore body text to 16px */ h1 { font-size: 3.2rem; } /* 32px — easier to read than 2rem */ p { font-size: 1.6rem; } /* 16px */
This approach is controversial — it overrides the user's default font-size preference at the root level. A safer alternative is to use the default 16px root and accept the decimal rem values.
:root { --fs-xs: 0.75rem; /* 12px */ --fs-sm: 0.875rem; /* 14px */ --fs-base: 1rem; /* 16px */ --fs-lg: 1.125rem; /* 18px */ --fs-xl: 1.25rem; /* 20px */ --fs-2xl: 1.5rem; /* 24px */ --fs-3xl: 1.875rem; /* 30px */ --fs-4xl: 2.25rem; /* 36px */ } h1 { font-size: var(--fs-4xl); } h2 { font-size: var(--fs-3xl); } p { font-size: var(--fs-base); }
Using rem for font-sizes ensures your design respects the user's browser font-size setting. Users who set their browser to 20px base will see all rem-based text proportionally larger, while px-based text stays the same fixed size.
Define a type scale in rem and reference it throughout your design system. This ensures visual consistency and makes global adjustments trivial.
Switch to pt-based units in print stylesheets, where physical measurements matter:
@media print { body { font-size: 12pt; } h1 { font-size: 24pt; } }
em is relative to the font-size of the parent element, while rem (root em) is always relative to the root element's font-size (typically 16px by default). This means rem values are predictable and consistent across your entire page, while em values can compound when nested. For example, 1.5rem always equals 24px (with default root size), but 1.5em inside an element with font-size: 20px equals 30px.
Divide the pixel value by the root font-size (usually 16px). Formula: rem = px ÷ 16. For example: 24px ÷ 16 = 1.5rem. If you've changed the root font-size to something other than 16px, divide by that value instead. Many developers set html { font-size: 16px; } explicitly to establish a predictable baseline.
html { font-size: 16px; }
rem is recommended for font-size because it respects the user's browser font-size preferences and makes global scaling easy. Change the root font-size and everything scales proportionally. Use px for properties that shouldn't scale with font preferences (borders, shadows, fixed-width elements). Many modern CSS frameworks like Tailwind use rem for typography by default.
By default, 1rem equals 16px because browsers set the root font-size to 16px. However, this can change if you set a custom font-size on the html element. If you set html { font-size: 10px; }, then 1rem = 10px. The "r" in rem stands for "root", so it always references the html element's font-size.
1rem
16px
html { font-size: 10px; }
The standard conversion is 1pt = 1.333px (or 4/3). Formula: px = pt × 4/3. For example, 12pt = 16px, 14pt ≈ 18.67px, 16pt ≈ 21.33px. This conversion is based on the CSS specification where 1pt = 1/72 of an inch and 1px = 1/96 of an inch. Note that pt is a print-oriented unit and should generally be avoided in CSS for screen-based designs.
1pt = 1.333px
px = pt × 4/3
📐 Stop calculating font sizes manually. Try our free Font Size Converter — instant px/rem/em/pt conversions with a visual preview.
px ↔ rem ↔ em ↔ pt instantly
Build beautiful gradient backgrounds
Convert colors between HEX, RGB, HSL