A List Apart


CSS Design: Size Matters

The Cascading Style Sheets (CSS) standard includes seven font-size keywords intended to give designers a simple means of setting font sizes without creating accessibility problems. Sizes range from xx-small to xx-large and are relative to users’ preferred “medium” settings. Putting these seven sizes to work should be a no-brainer. Unfortunately there are plenty of obstacles ahead. Fortunately there is a workaround. Let’s start by surveying the damage, then move on to a working solution.

Netscape 4

Article Continues Below

The first obstacle is Netscape 4, whose implementation of the keywords actually follows the CSS-1 spec’s suggested 1.5 scaling factor between indices. (In other words, ascending from smallest to largest, each keyword is 1.5 times bigger than the last.)

This is a terrible mistake, since “small” or “x-small” (let alone xx-small) can very easily slip under the smallest legible size when the user-chosen “medium” value looks reasonable. Similarly, larger sizes get comically big in a hurry.

I recommend that you contrive to withhold font sizes in keywords from Netscape 4.x by putting these rules in an imported sheet (via @import). Netscape 4 will then safely ignore your keyword-based rules, since the browser does not recognize stylesheets linked via @import. A List Apart uses a variant of this trick to hide its stylesheet from all 4.0 browsers.

If you can’t afford to let Netscape 4 users see default sizes for whatever HTML elements you’re using, you can specify sizes in px in the primary (importing) sheet, and override these rules in the imported sheet by writing selectors with greater specificity (explained below). Pixels have many drawbacks as a font size unit, but they are probably the best choice if you’re determined to use CSS to influence font size in Netscape 4.

IE4/5 Windows

The next big obstacle is reconciling WinIE4/5’s incorrect implementation of the keywords with the correct implementations of Netscape6+/Mozilla, Opera, and MacIE5/WinIE6 in “standards” mode. (Use complete, correct DOCTYPEs to switch these browsers to standards mode.)

The nature of the discrepancy is that WinIE4/5 implements “small” as the initial value, rather than “medium” as called for in CSS-1. The result is that without correction, all sizes specified in keywords will be one size smaller with respect to user preferences in conformant browsers than in WinIE4/5.

Fortunately, the techniques developed by Tantek Çelik to work around WinIE4/5’s incorrect CSS box model can also be used to fix the keywords bug.

A Working Example

Suppose you’ve got a rule in your primary “Netscape–4-safe” sheet that looks like this:

body, div, p, th, td, li, dd    {
    /* redundant selectors to help NS4 remember */
    font-family:  Verdana, Lucida, Arial, 
Helvetica, sans-serif;
    font-size:    11px;

Then in your secondary, imported sheet (which Netscape 4 can’t see) you can write:

body, body div, body p, body th, 
body td, body li, body dd    {
    /* more specific to override imported rule */
    font-size:    x-small;      
    /* false value for WinIE4/5 */
    voice-family: ""}"";   
    /* trick WinIE4/5 into thinking rule is over */
    voice-family: inherit;   
    /* recover from trick */
    font-size:    small
    /* intended value for better browsers */
    }html>body, html>body div, html>body p, 
html>body th, html>body td, 
html>body li, html>body dd    {
    font-size:    small
    /* be nice to Opera */

The confusion above tricks WinIE4/5 into applying the “corrected” size, gives others the right values (via rules with greater specificity), and even protects Opera from one of its bugs. (If you’re confused about what the increasingly specific CSS-2 selectors mean, try cutting and pasting them into the Opal Group’s SelectORacle.)

The result is “one step smaller than medium” text in all of the selected elements. In other words, small means small even in browsers that ordinarily get font size keywords wrong. Of course, you have to settle for a pixel-based version in Netscape 4, or simply let Netscape 4 users see unstyled markup, which they might prefer after all.

This method works as expected even when the selected elements are nested. By contrast, when you use em or percents for font size on elements that may nest, like <body>, <td>, <div> or <li> (as is effectively required by browsers with screwy inheritance models like WinIE4/5), there is always the danger that they will compound, resulting in type that is too small or too large.

Keywords are never too small, because as implemented in IE and Mozilla/Netscape 6, xx-small is always above the 9px threshold of adequate resolution for most fonts, regardless of the “medium” value.

Remember that your HTML must validate against one of the DTDs that put recent browsers into “standards” mode. And don’t put text you intend to style this way directly in <body> even though HTML 4.01 Transitional permits that.

An example of these techniques working together is available. {Ed. – A variant on the techniques described in this article controls text size in ALA 3.0.}

No Comments