px – em – % – pt – keyword

When it comes to setting the size of type in CSS, you have lots of options. You can apply a "keyword", like p { font-size: small; } or a numerical value. When using a value, you need to declare a unit of measure which itself has four options. Which is best? It depends of course. Let's take a look:

Keyword

Valid options for setting font-size in keyword are xx-small, x-small, small, medium, large, x-large, and xx-large as well as relative keywords smaller and larger.

Surprisingly enough, keyword sizing is pretty consistent across browsers and platforms. See below a test page in Opera, Firefox, IE 6, and Safari:

Note that although the they are pretty close, there are differences in where the lines break and total paragraph height.

Only when one of the relative sizing keywords are used does the "cascade" kick in and the font-size of the parent element effects the child. For example, if the parent was set to medium and the child was set to large. Only large would be used to size the child element. However, if the parent was set to medium and the child was set to larger (note, larger not just large), the child would be "sized up" to be larger than the parents font size. Change the parent, change the child, hence a "cascade".

Keywords are a perfectly fine way to size fonts on the web. One of the more popular techniques is to set a keyword font-size on the body element, and then use relative font-sizing every where else on the page. This gives the ability to really easily size up or down the font size on the page (e.g. with JavaScript) and have the whole page move up and down in size consistently.

However, keywords don't offer very fine-grained control of your typography, as the choices are fairly limited.

px

If you need fine-grained control, sizing fonts in pixel values (px) is an excellent choice (it's my favorite). On a computer screen, it doesn't get any more accurate than a single pixel. With sizing fonts in pixels, you are literally telling browsers to render the letters exactly that number of pixels in height:

Windows, Mac, aliased, anti-aliased, cross-browsers, doesn't matter, a font set at 14px will be 14px tall. But that isn't to say there won't still be some variation. In a quick test below, the results were slightly more consistent than with keywords but not identical:

Due to the nature of pixel values, they do not cascade. If a parent element has an 18px pixel size and the child is 16px, the child will be 16px. However, font-sizing settings can be using in combination. For example, if the parent was set to 16px and the child was set to larger, the child would indeed come out larger than the parent. A quick test showed me this:

"Larger" bumped the 16px of the parent into 20px, a 25% increase.

Pixels have gotten a bad wrap in the past for accessibility and usability concerns. In IE 6 and below, font-sizes set in pixels cannot be resized by the user. That means that us hip young healthy designers can set type in 12px and read it on the screen just fine, but when folks a little longer in the tooth go to bump up the size so they can read it, they are unable to. This is really IE 6's fault, not ours, but we gots what we gots and we have to deal with it.

Setting font-size in pixels is the most accurate (and I find the most satisfying) method, but do take into consideration the number of visitors still using IE 6 on your site and their accessibility needs. We are right on the bleeding edge of not needing to care about this anymore.

em

Em values are probably the most difficult values to wrap the ol' noodle around, probably because the very concept of them is abstract and arbitrary. Here's the scoop: 1em is equal to the current font-size of the element in question. If you haven't set font size anywhere on the page, then it would be the browser default, which is probably 16px. So by default 1em = 16px. If you were to go and set a font-size of 20px on your body, then 1em = 20px.

Historically I think the "em" value is based on the width of the uppercase M, but don't quote me on that.

Things start to get slightly more complicated with em's when we start setting up more complex font sizing. Say we need a header with a larger font-size, so we set h1 { font-size: 2em; } That "2" is essentially a multiplier of the current em value. So if the current em size is 16px, that header tag is going to turn out to be 32px. That math works out cleanly, but you can imagine that it often doesn't and rounding needs to take place.

The most popular method in working with em values is to set the font-size on the body to 62.5%. Because the default browser font-size is 16px, this makes it 10px (without hard-setting it to 10px, which wouldn't cascade). Using 10 as a multiplier is much easier than using 16. This way, you need a font size of 18px? Use font-size: 1.8em.

So why both with all this em business when it's just an abstraction of using pixel values anyway? Three possible reasons:

The ARE resizeable in IE 6

The relationship to other sizes (elastic width sites)

Em's cascade like a mo-fo

The first one is the big one. If you basically want to use pixels but don't like the accessibility problems, em's may be the ticket for you.

Em's aren't just for fonts, it's a unit of measure that you can use for any other length (height, width, etc). Elastic width sites use em values for everything, which essentially makes the site "zoomable", meaning that when you bump the font-size up everything bumps up all the way down to the width of the site. Em's have a direct relationship to each other in this way. If you have a box that is 10em in height, and a font inside that is 1em in size, it will take up exactly 1/10 the height of that box. That exact proportional relationship makes em values a powerful web design technique.

There is one potential concern with em's, with regards to #3. They do indeed cascade. Every em value is relative to its parents value. If you are using em's as a straight substitution for pixel values, this can cause problems. For example, you might set both your "p" (paragraph) and "li" (list item) font-sizes to be 1.2em. Looks great for you today, but tomorrow some content is published to the site that has a paragraph inside a list item. Those two values will cascade (1.2 x 1.2) and that list item will be bigger in font-size than any of the others. No way around that, other than removing the tag.

%

Percentages are fairly obvious in how they work. That is, they work just how you think they will. If a parent has the font-size of 20px and the child has a font-size of 50%, it will come out to 10px. Just like em's the very nature of percentage sizing is that it is relative. It also cascades in the same way, so the very problem described above of the list item and the paragraph item applies here as well.

A popular technique using percentages for font-sizing is to set a reasonable font size on the body (like "small") and then using percentages for everything else. This allows you to swap out that keyword in a single place in order to scale the font sizing on the entire page, which makes things like a font-resizer interface feature a lot easier.

pt

The final unit of measurement that it is possible to declare font sizes in is point values (pt). Point values are only for print CSS! A point is a unit of measurement used for real-life ink-on-paper typography. 72pts = one inch. One inch = one real-life inch like-on-a-ruler. Not an inch on a screen, which is totally arbitrary based on resolution.

Just like how pixels are dead-accurate on monitors for font-sizing, point sizes are dead-accurate on paper. For the best cross-browser and cross-platform results while printing pages, set up a print stylesheet and size all fonts with point sizes.

For good measure, the reason we don't use point sizes for screen display (other than it being absurd), is that the cross-browser results are drastically different:

I find it easier to do my ie testing from an old laptop that I have set up beside my desk. I leave windows on it and run a multiple ie program: http://tredosoft.com/Multiple_IE . This allows me to install ie 6 (and older versions) while ie 8 is installed.

I have been struggling with ems for a while now, but after reading this, might switch over to percentages. Still some cascading to think about, but at least I can get the numbers so they won’t be so arbitrary as ems always seem to turn out.

http://www.w3.org/TR/css3-values/#relative0
The ‘ex’ unit is defined by the font’s x-height. The x-height is so called because it is often equal to the height of the lowercase “x”. However, an ‘ex’ is defined even for fonts that don’t contain an “x”.

CSS3 also has some new ones:
gd the grid defined by ‘layout-grid’ described in the CSS3 Text module [CSS3TEXT]
rem the font size of the root element
vw the viewport’s width
vh the viewport’s height
vm the viewport’s height or width, whichever is smaller of the two
ch The width of the “0” (ZERO, U+0030) glyph found in the font for the font size used to render. If the “0” glyph is not found in the font, the average character width may be used.

It’s true, you are right. But I disagree that’s the “beauty” of ems =). I find that to be a pain. What about nested lists that are 5 levels deep? That’s a lot of extra CSS to widdle your way back down to fight against the cascade.

Snookerman, thanks SOOO much for posting this comment. I never realized you can do things this way. And I fool used a separate classes for everything! NO MORE, thanks to you!
PS: By ‘never’ I mean since I started to learn CSS, which was 6 month ago.

Of course, big thanks go to Chris too, I learned so much from his articles, and this article is no exception.

Yes, you are right again, not sure what I was thinking. Unless the “nesting” isn’t just straight lists, like a paragaph inside definition list inside a unordered list inside a div, that kind of thing. But if you are doing that kind of thing you are probably well aware and can deal with it.

I do think the fact remains that it’s not quite as intuitive as setting a pixel value, in that you need to account for these (potentially unforeseen) circumstances.

That is true, ems can be a bit tricky. However, the more you use them and understand you they work, the more you are amazed of how much easier they make certain things. For example, I use the following rule:

p {
max-width: 30em;
}

This means that I will always have the same number of characters per line, regardless of the font size. If I would use pixels, I would have to recalculate and change the width of the paragraph every time I changed the font size. My design would also break if someone used a different text size. The only way to avoid that is to use ems.

The problem with IE tab for firefox is it uses the version of IE happens to be installed on your computer (in my experience with windows anyway). So if you’ve installed 7 it will only render as version 7. IETester provides for all versions up to the latest one you have installed. IEtester for IE6 gets a bit funky with really advanced layouts, but generally those aren’t the kind that have IE6 support in mind anyway.

I wanted to share my personal experience with em based design.
I stared using em seriously when I designed Emastic, in the beginning is little hard to switch from px to em but once you learnt how to use everything becomes more organized.

It’s not all about resize in IE6, Crome 1 and Safari 3 it is about more organized CSS. Also imagine the power that by changing one central parameter everything will change. Imagine one client saying to you “can this site be littttle more bigger or smaller” and you are saying yeah just a sec. you are going to the body( text-size) and from 1em you are writing 1.1em and all the site including the images is getting bigger. Try to built your next site with ems you will learn to love them :)

Paul Hayes defined it correctly, but i want to point out that not all browsers are able to actually compute the ex size. Some browsers will just use an arbitrary 2ex=1em rule.

em, % and cascade

When used for font-size, ems and percentages are basically the same. You may use one or the other, whether you prefer percentages or decimal ratios.

When thing to keep in mind when using relative units such as % and em: don’t apply them on generic HTML elements (except html or body). Do apply them on containers, or specific elements within a container (when you know what the contents or gonna be), but beware of applying them too early in the structure.

Oh, and define a standard font-size for your body that matches the size you need for body text. If most text in your layout is 12px, then define font-size:75% or font-size:.75em for body. Then you may need to reduce the size of some text (font-size:83%, font-size:.92em…) or make titles bigger. But settling on a “convenient” 10px font-size for body, when what you actually need is text that ranges between 11px and 18px, will get troublesome as exemplified by the cascading issue you suggested.

Points are for print? Nope.

Points are not for print exclusively. Theoretically, points are for defining an absolute measure. Pixels are not absolute, since depending on your screen and chosen definition (not resolution), the resolution (pixels per inch) can go from a lot (150dpi) or very little (75dpi). Which means your pixels can be a size, or maybe half that size. Which means that text you design to be perfectly legible on your screen may look too big on your client’s screen (“please make the text smaller, ok?”) or too small to be readable on your neighbor’s screen (“hey, the website you told me about the other day? the one you said you had worked on… well i couldn’t read the text very well, it’s so small”).

Points are a solution to this issue. But browsers and operating systems need to manage those. Basically, it means:

browsers have to calculate the display size in pixels using the given value (say, 10pt) and the screen’s real resolution;
operating systems have to communicate the real current resolution, and not a default value.

I’m not sure what’s the current situation for those two criterion, in today’s browsers and OSs.

I found that some browsers scale differently depending on using em or % (at least as base), e.g. with one of them the font size would increase much more every step increasing it via text size option. Could be that it was IE only, don’t remember exactly.

I didn’t realize points were intended to work that way on the web. It’s definitely a smart idea. But clearly, it’s not reliable. Hopefully it will be someday, as the variance in screen resolutions and pixel sizes is getting much wider.

I know that using px will force the font size to be exact even if the user changes their browser’s default font size or their operating system’s font size (in Windows’ Display Properties you can set it to use Normal, Large or Extra Large fonts). Are there any distinctions between keyword, % or em in respect to handling users that have bumped up (or down) their base font size?

“Here’s the scoop: 1em is equal to the current font-size of the element in question. If you haven’t set font size anywhere on the page, then it would be the browser default, which is probably 16px. So by default 1em = 16px. If you were to go and set a font-size of 20px on your body, then 1em = 20px.”

1em is equal to whatever font size you have set in your browser settings. So your statement is mostly inaccurate.

This has given me a good understanding of web typography and how to use the different mediums smoothly. I found it very easy to wrap my head around the em logic. I’ll make sure to factor these into the next layout I build.

Excellent article. Like everything there just is no perfect solution. I tend to use ems because I like the additional flexibility they provide, but I often run into annoying issues with the cascading sizes. As noted in the discussion above, that’s very much the case when you have different types of elements nested inside each other, where simple CSS doesn’t fix the issue (so the li inside a p inside a div type concern).

Link to the em calculator in the comments is invaluable, never run across that before!

You are correct that an em is the width of an “M”, thus the word “em”. It’s simply a typesetting term for the maximum width of any letter in a font which will be the width of “M”.

I’ve read arguments pro/con about all measurements, but decided that em’s are for me. I understand them and use them for all measurements throughout my sites. In other words, I don’t mix methods and that’s where I think many people have problems.

As far as cascading problems, I simply start every rule that has an em measurement in it with “font-size: 1em;” — that sets the size and solves any cascading problems.

You can use em’s to set the size of graphics as well so that they zoom along with text zoom — it’s something I call “Zoom-Cooperative”. Here’s an example: http://sperling.com/examples/zoom/

So, all in all, if a person can get their head around the concept of em’s, I think it will serve them well over the years and present less problems than other measurements.

Wel, yes. 16px is 16px. What I don’t think you realize is while 16px may be “medium” and easy to read on your computer, that’s not universally true. On my IBM laptop, for example, 16px is considerably smaller than “medium”. That’s why I think it’s better to assume that your visitors can read 100% — and any other assumption is pure conjecture.

Using of px or em is bad. The character size depend of the dpi of the used display. If you have 1em = 10 px, the character height will be 10 pt on a display with 72 dpi and 5.45 pt on s screen with 132 dpi. The result is that the textes will not be readable on all hardare.

Please don’t use px to set font sizes. This is very frustrating to readers, because it varies from screen to screen depending on their resolution. If they have a screen with high DPI, your fonts will be too small to read, forcing them to set a minimum font size (which breaks your layout) or zoom in (which breaks your layout). Use sizes that stay the same from screen to screen.

An “em” is a typographical measurement which goes back to letterpress days. It refers to the height of the piece of metal (or wood) that any letter in a given type font is mounted on (here I am using type font in its true meaning which is one size of one style of type). Typically the capital M was a square piece and therefore the measure became known as an “em”. Another typographical measurement is the “en” which is one-half of an em.

X-height does refer to the height of a small letter but more correctly refers to the height of the type font characters which do not have ascenders or descenders (i.e., b,d,g,p, etc.). the height is measured from the baseline to to top of the highest letter. That means that in some fonts (Garamond comes to mind) the x-height is higher than the small “x”, because of the height of the rounded letters (a, c, m, etc.).

Few designers today have handled lead type or even studied the history and origins of the typefaces they use. Many would argue it makes little difference. I think we would have fewer illegible pages.

body{font-size:10px;}
.child_percentage{ font-size:1em;border:1px solid #ccc;padding:100%;margin:100% } — as per calculation, 1em == 10px == 100%. if we apply for padding or margin. it does not work as expected

I hate to comment on such an old article, but you left off what seems (to me) the best version – “multipliers”.

Instead of “1.3em” – just “1.3”.

There seems to be an issue, that when setting line-height: 1.3em cascades, it does so at a fixed pixel value relative to the current font-size.

So, when using “1.3em” if a span or something increases that font-size, the line-height is not increased. But if you’re using just a multiplier “1.3”, then it is increased/recalculated for the “internal” span.

Thank god there is notepad++, where you can use regular expressions and replace everything that matches you criteria. Try it it will ease everything up. No need to replace every item on the code manually.

👋

CSS-Tricks* is created, written by, and maintained by Chris Coyier and a team of swell people. The tech stack for this site is fairly boring. That's a good thing! I've used WordPress since day one all the way up to v17, a decision I'm very happy with. I also leverage Jetpack for extra functionality and Local for local development.