Thursday, March 16, 2006

How Many Pixels in an EM?

In the interest of creating CSS-only layouts, it often makes sense to emulate CSS properties that IE doesn't support by using IE-only expressions. An example is the work of Svend Tofte in emulating max-width, which I reference quite often even though it is now 2 years old. I recently created a min-width expression based on this. Here is Svend's expression for max-width:

width:expression( document.body.clientWidth > (500/12) *
parseInt(document.body.currentStyle.fontSize)? "30em": "auto" );


Quite nice, but requires a bit of experimentation to get it to work right. In Svend's words:

Basically, with document.body.clientWidth, we get how wide the browser
window is. Using parseInt(document.body.currentStyle.fontSize), we get the font
size in pt's, that the user has currently set. I experimented, and at 12pts (the
normal size), the browser window gets wider then 30em's, at more or less 500
pixels. Of course, it's then a small matter, of calculating backwards, in the
scale, and see, if that if the default font size is 14pt (larger), then 30em's
will be exceeded at 583 pixels (roughly). The sad thing is, that you will need
to find the magic number, for whatever width you want for your letters. For
30ems, 500 pixels is the magic number.


Just as a reference for myself, I began tabulating the width of a 1em-wide div at various font sizes. In other words, I took screen captures and measured them in Photoshop.


body{
font-size: 500pt;
}

div{
background-color:black;
width:1em;
}

This yields a div that is 667 pixels wide.

Then I realized that if I graphed the pixel width of the div versus the font size in ems, a nice curve emerged, which meant to me that there must be a common factor. So, I took the pixel width of the largest measurement and divided it by the pt size of the font:

667px/500pt = 1.334

A little bit of algebra yields the formulae:

px per em = 1.334 * pts

and

px = ems*1.334*pts

I tested this out in IE and Firefox with serif, sans-serif, and monospaced font families, and it holds true regardless of font size. Applying it to Svend's original expression gives me the following max-width expression (where the desired max-width = 30em):

width:expression( document.body.clientWidth > (30*1.334)*
parseInt(document.body.currentStyle.fontSize)? "30em": "auto" );

Hope you like it... Please comment if you find it doesn't work for you!

Was this post helpful to you? If so, please consider making a small donation to keep this blog going.

3 Comments:

Anonymous Anonymous said...

What happens if you set the font size to large? Not in the browser, but in the OS itself. That changes the dpi, and I wouldn't be surprised if that renders your formula invalid. Hardcoding things is almost always a bad idea.

12:52 AM  
Blogger tom said...

A quick test shows that the formulas hold true even when the font size is changed on the OS level. Changing the font size for the OS doesn't change the dpi of your display.

However, you do raise a really good point: the number of pixels per em does change with the screen resolution. I'll devote another post to this so it doesn't get buried in the comments.

7:35 AM  
Anonymous Anonymous said...

Couldn't you have just used 96dpi/72dpi to get 1.3333 pixels per EM unit?

11:47 AM  

Post a Comment

<< Home