CSS font size: relative vs. absolute values. Which to use?

  • What's the best way to size text across browsers?
  • What are the advantages and disadvantages of defining font size in pixels / em?

Answers


Which to use?

Both. Relative for main body text that users are going to have to read a lot of (so they'll want to be able to read it comfortably); Absolute for text that has to be sized to match other elements on the page that are sized in pixels, such as images.

For relative, ‘%’ and ‘em’ are equally good.

For absolute, always use ‘px’. Never use ‘pt’ for on-screen use, it is only sensible for print stylesheets. It is a pity that ‘pt’ is considered the default unit for font-handling because on the web it is the worst possible choice.

(ETA: Note that since this answer, CSS3 has redefined the ‘physical units’ so that px and pt are always proportional. So this problem no longer matters unless you are concerned about very old browsers.)

Some people don't like the ‘compounding’ effect of relative font sizes. The trick, really, is to use as few font-size changes as you can, to avoid too many nestings. It should be possible to get the relative-to-user's-preferred-size behaviour without the compounding behaviour by using the font-size keywords ‘small’/‘medium’/‘xx-large’/etc., but unfortunately that way you don't get much granularity, and there are still even today differences between how the browsers handle them.


I keep the font size as the user's chosen default, then use relative sizing:

body {
    font-size: 100%;
}

p {
    font-size: 1em;
}

h1 {
    font-size: 1.8em;
}

This method respects the user's choice of font size in their browser, which is usually set to 16px.


Personally I set an absolute font size on the body and from there set everything as relative to that. eg:

body {
    font-size: 10px;    /* or pt if you want */
}
h1 {
    font-size: 200%;
}

Just try to avoid combining compounded relative sizes:

body {
    font-size: 10px;
}
p {
    font-size: 80%; /* 8px, right? */
}
div {
    font-size: 150%;
}
/* what size is a "div > p" ? */

All the modern browsers have full-page zoom these days, meaning that even sizing your font in pixels is ok.

The benefit to this method is that you can easily size up or down all your text by changing one definition.

The downside is that if you want to change the default font size, but not the headings (for example), then there'd be a lot of declarations to change.


A List Apart did an extensive write up on how font sizes work in various browsers. It turns out to be more complicated than you'd expect, just like everything else in CSS. The consensus seems to tilt toward using ems, since that gives the user more control over adjusting the font size in the browser.


I prefer relative values since the Internet Explorer (< 7?) cannot scale absolute or pixel values.


One thing I've seen people use is to define a base font size in the body CSS (e.g., 12pt) and then all other font sizes are percentages of that (e.g., 140% for titles, 80% for small, etc).

If you use pt then you'll have differences in display based upon the user's set DPI, but it will be under the control of the user, perhaps.

If you use px then you'll have problems on very high DPI devices.

Em and pt are good for CSS for printing.

There's a lot of do it and see what happens about fonts and CSS.


If you use absolute sizes then any visually impaired readers might find it hard to read. If you use relative sizes then you are merely specifying which text is larger / smaller than other text on your page, all relative to the user's default text size which might be large (if impaired) or tiny (if a bit weird).

A disadvantage of relative sized text is when you want your website to be fixed sizes, but if possible you should really go with a more fluid design anyway so that the page resizes to accomodate its content.


Pixels are a fixed size. This means that when viewed on any screen and resolution the text will always be the same size.

Em's are scalable which means that people on different screen sizes and resolutions can generally get a better experience.

Certain browsers have issues altering the size of fixed font-size types (px and pt) and therefore tend not to be very good for web font as some users may need to increase the size of your font using a screen magnifier or just the mouse wheel.

Relative font-sizes have a habit of irritating ignorant designers who get irked that the web site doesn't correspond exactly to their designs.

In my mind, mollifying designers who should know better is not enough of a reason to ever use fixed fonts in web development.


Using EM scaling is more versatile with fonts. It is also more accessible.

If you haven't worked with this before, a tool like Em Calculator can be very useful to understanding how the tag/model works.


Using relative sizes will make your page look better on mobile devices such as the iPhone, especially since they render the page on a larger viewport then scale it down to fit in the needed space.


If you can drop support for IE8 then I suggest using rem units. They are relative units like em but they do not cascade to children elements making them much simpler to work with

em are complex

p {
  font-size: 2.5em;
  span {
    font-size: 1.5 em;
    /* font size comes out to 3.75 root em*/
  }
}

rem are simpler

p {
  font-size: 2.5rem;
  span {
    font-size: 1.5 rem;
    /* font size comes out to 1.5 root em*/
  }
}

Most of my programming background is desktop applications but I've been reading a fair amount for web development recently, and the books I've come across suggest using a keyword font size specification (small, medium, etc) and then scaling that up or down by percentage or em.

If your font size is specified in px, users of old versions of IE won't be able to override the size of the text, i.e., they won't be able to make it larger or smaller to suit their preferences.

However, IE5 also poses a problem when your font size is specified by keyword: relative to other browsers, IE5 displays the text about one step larger.


Need Your Help

Why does drawRect: work without calling [super drawrect:rect]?

ios core-graphics

I'm overriding drawRect: in one of my views and it works even without calling [super drawrect:rect]. How does that work?

Use printf to format floats without decimal places if only trailing 0s

c printf

Is it possible to format a float in C to only show up to 2 decimal places if different from 0s using printf?