How to specify dynamic font sizes consistently with CSS

This artice is also available in a French translation.

When developing web sites, we naturally want to offer our end users the option to freely resize the text size in their web browser of choice to their liking. What I would like to do here is present what I’ve found to be most consistent way to achieve this with CSS.

The problem

The problem, as almost always, comes down to web browsers. In this situation, it is Internet Explorer that doesn’t allow the user to resize any font set with the px (pixel) unit, but instead only those with other units, such as percentage, em etc. This problem still applies to IE 7 as well, although that version at least offers page zooming (which is altogether different from text resizing, though).

This is a problem, since most designs and wanted end results are based in pixels, and there are different ways to accomplish this end goal in a coherent manner with other units.

The solution I use

First, it’s about choosing a unit for font sizes. I’ve decided to go with the em unit here, since it seems to be the most stable and accordingly implemented one. One em used for font size equals the font size of the parent element.

So, let’s start from the top:

The default text size in most (I’d like to say all, but who knows…) modern web browsers is 16 pixels, and that will be the base for our code. To make sure all our font sizes derive from that, we start by setting the font size to 100% on the html element:


html{
    font-size: 100%;    
}

The next step is to decide the default text size for the web site, i.e. the font size that will be the most commonly used one for most of the text, and also a good ground to stand on for calculating the text size for all other elements. Let’s say we want a web page where the general font size is 10 pixels. We then take the desired font size, 10, and divide it with the default web browser size, 16: 10 / 16 = 0.625. This is the value that we use for the em unit on the body element:


body{
    font: 0.625em/1em Verdana, Geneva, Arial, Helvetica, sans-serif;
}

The result of this is that the font size will be 10 pixels for all text in the web page, unless you explicitly specify something else. If, for example, you then (which seems very likely) want to have a different font size for different heading types, the calculation is then based on the value you have set for the body element.

This means that 1em set as font size for any child element of the body element will equal 10 pixels. Let’s say that you want your h1 element to have a font-size of 17 pixels, you need to calculate the em value like this: 17 / 10 = 1.7. The resulting code for h1 elements would then look like this:


h1{
    font: 1.7em/1em Arial, Helvetica, sans-serif;
}

From that on, it’s fairly simple. Just make sure to start your calculations with the default font size set (in this case, 10 pixels), and also, use a calculator to assure that your values are rounded correctly (otherwise, different web browsers will do different rounding for you, resulting in inconsistency).

Note: form elements

To reach a more consistent result with form elements as well, I recommend that you specify the font sizes form them as 100%:


input, select, textarea{
    font-size: 100%;
}    

End user experience

With the code displayed above, the font size in web browsers will be 10 pixels, when the web browser font size setting is set to normal (i.e., the web browser’s default font size). Then, if the user resizes the text in any direction, it will automatically adapt itself in well-balanced steps and enhance the end user experience.

An example font style sheet

In the projects I work on, I usually have all the font size settings in a separate CSS file, to easily get an overview of it, and also to separate font settings from CSS used solely for layout purposes. Here’s what an example font CSS might look like for me:


/* Tag-specific */
html{
    font-size: 100%;    
}

body{
    /* The default font size will be 10 pixels with the default web browser font size setting*/
    font: 0.625em/1em Verdana, Geneva, Arial, Helvetica, sans-serif;
}

input, select, textarea{
    font-size: 100%;
}

h1{
    /* This font will be 20 pixels with the default web browser font size setting */
    font: 2em/1em Verdana, Geneva, Arial, Helvetica, sans-serif;
}

h2{
    /* This font will be 15 pixels with the default web browser font size setting */
    font: 1.5em/1em Arial, Helvetica, sans-serif;
}

h3{
    /* This font will be 12 pixels with the default web browser font size setting */
    font: bold 1.2em/1em Verdana, Geneva, Arial, Helvetica, sans-serif;
}    

For discussion

Since all web browsers but IE offer resizing of fonts set in pixels directly, and IE 7 totally relies on page zoom and has hidden away text resizing deep down, is it about time to start specifying font sizes with pixels instead? Or is a more dynamic font size value still they way to go, even though it might require some calculations and less readable/understandable code.

 

Related reading

Posted in CSS,Developing,Technology |

Leave a Reply

Your email address will not be published. Required fields are marked *