Book HomeCascading Style Sheets: The Definitive GuideSearch this book Friday 20th of April 2018 04:39:35 PM

5.2. Font Weights



normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900

Initial value




Applies to

all elements

Even though you may not realize it, you're already familiar with font weights: boldfaced text is a very common example of an increased font weight. Generally speaking, the darker and "more bold" a font appears, the heavier it is said to be. There are a great many ways to label the heaviness of fonts. For example, the font family known as Zurich has a number of variants such as Zurich Bold, Zurich Black, Zurich UltraBlack, Zurich Light, and Zurich Regular. Each of these uses the same basic font, but each has a different weight.

So let's say that you want to use Zurich for a document, but you'd like to make use of all those different heaviness levels. You could refer to them directly through the font-family property, but you really shouldn't have to do that. Besides, it's no fun having to write a style sheet such as this:

H1 {font-family: 'Zurich UltraBlack', sans-serif;}
H2 {font-family: 'Zurich Black', sans-serif;}
H3 {font-family: 'Zurich Bold', sans-serif;}
H4, P {font-family: Zurich, sans-serif;}
SMALL {font-family: 'Zurich Light', sans-serif;}

Besides the obvious tedium of writing such a style sheet, it only works if everyone has these fonts installed, and it's pretty safe bet that most people don't. It would make far more sense to specify a single font family for the whole document and then assign weights to various elements. You can do this, in theory, using the various values for the property font-weight. A fairly obvious font-weight declaration is this:

B {font-weight: bold;}

This says, simply, that the B element should be displayed using a boldface font; or, to put it another way, a font that is heavier than is normal for the document, as shown in Figure 5-8. This is what we're used to, of course, since B does cause text to be boldfaced.

Figure 5-8

Figure 5-8. Making the B tag bold

However, what's really happening is that a heavier variant of the font is used for displaying a B element. Thus, if you have a paragraph displayed using Times, and part of it is boldfaced, then there are really two variants of the same font in use: Times and TimesBold. The regular text is displayed using Times, and the boldfaced text uses TimesBold.

5.2.1. How Weights Work

In order to understand how a user agent determines the heaviness, or weight, of a given font variant, not to mention how weight is inherited, it's easiest to start by talking about the keywords 100 through 900. These number keywords were defined to map to a relatively common feature of font design in which a font is given nine levels of weight. OpenType, for example, employs a numeric scale with nine values. If a font has these levels built in, then the numbers are mapped directly to the predefined levels, with 100 as the lightest variant of the font, and 900 as the heaviest.

In fact, there is no intrinsic weight in these numbers. The CSS specification says only that each number corresponds to a weight at least as heavy as the number that precedes it. Thus, 100, 200, 300, and 400 might all map to the same relatively lightweight variant, while 500 and 600 could correspond to the same heavier font variant, and 700, 800, and 900 could all produce the same very heavy font variant. As long as no keyword corresponds to a variant that is lighter than the variant assigned to the previous keyword, then everything will be all right.

As it happens, these numbers are defined to be equivalent to certain common variant names, not to mention other values for font-weight. 400 is defined to be equivalent to normal, and 700 corresponds to bold. The other numbers do not match up with any other values for font-weight, but they can correspond to common variant names. If there is a font variant labeled something such as "Normal," "Regular," "Roman," or "Book," then it is assigned to the number 400 and any variant with the label "Medium" is assigned to 500. However, if a variant labeled "Medium" is the only variant available, it is not assigned to 500.

A user agent has to do even more work if there are less than nine weights in a given font family. In this case, it has to fill in the gaps in a predetermined way:

In order to understand this more clearly, let's look at three examples of font-weight assignment. In the first, assume that the font family Karrank% is an OpenType font and so already has nine weights already defined. In this case, the numbers are assigned to each level, and the keywords normal and bold are assigned to the numbers 400 and 700, respectively.

In our second example, we consider the font family Zurich, which was discussed near the beginning of this section. Hypothetically, its variants might be assigned values for font-weight as shown in Table 5-3.

Table 5-1. Hypothetical Weight Assignments for a Specific Font

elements, although as we can see in Figure 6-12,this would have the effect of setting that color on all inputs, fromtext to radio-button to checkbox inputs:

SELECT {color: rgb(33%,33%,33%);}INPUT {color: gray;}
Figure 6-12

Figure 6-12. Changing form element foregrounds

Note in Figure 6-12 that the text color next to thecheckboxes is still black. This is because we've only assignedstyles to elements like INPUT and

Font Face

Assigned Keyword

Assigned Number(s)

Zurich Light

100, 200, 300

Zurich Regular



Zurich Medium


Zurich Bold


600, 700

Zurich Black


Zurich UltraBlack


The first three number values are assigned to the lightest weight. The Regular face gets the keywords 400 and normal, as expected. Since there is a Medium font, it's assigned to the number 500. There is nothing to assign to 600, so it's mapped to the Bold font face, which is also the variant to which 700 and bold are assigned. Finally, 800 and 900 are assigned to the Black and UltraBlack variants. Note that this last would only happen if those faces had the top two weight levels already assigned. Otherwise, the user agent might ignore them, and assign 800 and 900 to the Bold face instead, or it might assign them both to one or the other of the Black variants.

Finally, let's consider a stripped-down version of Times, in which there are only two weight variants, TimesRegular and TimesBold, as shown in Table 5-2.

Table 5-2. Hypothetical Weight Assignments for Times

Font Face

Assigned Keyword

Assigned Number(s)



100, 200, 300, 400, 500



600, 700, 800, 900

The assignment of the keywords normal and bold is straightforward enough, of course. As for the numbers, 100 through 300 are assigned to the Regular face because there isn't a lighter face available. 400 goes to Regular as expected, but what about 500 ? It is assigned to the Regular (or normal) face because there isn't a Medium face available; thus, it is assigned the same as 400. As for the rest, 700 goes with bold as always, while 800 and 900, lacking a heavier face, are assigned to the Bold font face. Finally, 600 is assigned to the next-heavier face, which is, of course, the Bold face.

font-weight is inherited, so if you set a paragraph to be bold, then all of its children will inherit that boldness, as we see in Figure 5-9. {font-weight: bold;}
Figure 5-9

Figure 5-9. Inherited font weight

This isn't unusual, but the situation gets interesting when you use the last two values we have to discuss: bolder and lighter. In general terms, these keywords have the effect you'd anticipate: they make text more or less bold with comparison to its parent's font weight. Let's consider bolder first.

5.2.2. Getting Bolder

If you set an element to have a weight of bolder, then the user agent first must determine what font-weight was inherited from the parent element. It then selects the lowest number which corresponds to a font weight darker than what was inherited. If none is available, then the user agent sets the element's font weight to the next numerical value, unless the value is already 900, in which case the weight remains at 900. Thus, you might encounter the following situations, illustrated in Figure 5-10:

P {font-weight: normal;}
P EM {font-weight: bolder;}  /* results in 'bold' text, evaluates to '700' */
H1 {font-weight: bold;}
H1 B {font-weight: bolder;}  /* if no bolder face exists, evaluates to '800' */
P {font-weight: 100;} /* assume 'Light' face exists ; see explanation */
P STRONG {font-weight: bolder;} /* results in 'normal' text, weight '400' */
Figure 5-10

Figure 5-10. Text trying to be more bold

In the first example, the user agent moves up the weight ladder from normal to bold ; in numeric terms, this is a jump from 400 to 700. In the second example, H1 text is already set to bold. If there is no bolder face available, then the user agent sets the weight of B text within an H1 to 800, since that is the next step up from 700 (the numeric equivalent to bold). Since 800 is assigned to the same font face as 700, there is no visible difference between normal H1 text and boldfaced H1 text, but nonetheless the weights are different.

In the last example, paragraphs are set to be the lightest possible font weight, which we assume exists as a Light variant. Furthermore, the other faces in this font family are Regular and Bold. Any EM text within a paragraph will evaluate to normal, since that is the next-heaviest face within the font family. However, what if the only faces in the font are Regular and Bold ? In that case, the declarations would evaluate like this:

/*   assume only two faces for this example: 'Regular' and 'Bold'   */
P {font-weight: 100;}   /* looks the same as 'normal' text */
P SPAN {font-weight: bolder;}   /* maps to '700' */

As we can see, the weight 100 is assigned to the normal font face, but the value of font-weight is still 100. Thus, the SPAN text (which is set to be bolder) will inherit the value of 100 and then evaluate to the next-heaviest face, which is the Bold face and which has a numerical weight of 700. Figure 5-11 shows us the visual result of all this.

Figure 5-11

Figure 5-11. Greater weight will usually confer visual boldness

Let's take this all one step further, and add two more rules, plus some markup, to illustrate how all this works (see Figure 5-12 for the results):

/*   assume only two faces for this example: 'Regular' and 'Bold'   */
P {font-weight: 100;}   /* looks the same as 'normal' text */
P SPAN {font-weight: 400;}   /* so does this */
STRONG {font-weight: bolder;}   /* bolder than its parent */
STRONG B {font-weight: bolder;}   /* bolder still */
This paragraph contains elements of increasing weight: there is an
<SPAN>SPAN element which contains a <STRONG>strongly emphasized
element, and that contains a <B>boldface element</B></STRONG></SPAN>.
Figure 5-12

Figure 5-12. Moving up the weight scale

In the last two nested elements, the computed value of font-weight is increased because of the liberal use of the keyword bolder. If we were to replace the text in the paragraph with numbers representing the font-weight of each element, we would get the results in Figure 5-13:

100 <SPAN> 400 <STRONG> 700 <B> 800 </B></STRONG></SPAN>.
Figure 5-13

Figure 5-13. Changing weight, with the numbers to illustrate it

The first two weight increases are large because they represent jumps from 100 to 400, and from 400 to bold (700). From 700, there is no heavier face, so the user agent simply moves the value of font-weight one notch up the numeric scale (800). Furthermore, if we were to insert a STRONG element into the B element, it would come out like Figure 5-14:

100 <SPAN> 400 <STRONG> 700 <B> 800 <STRONG> 900
Figure 5-14

Figure 5-14. Weight numbers, again

If there were yet another B element inserted into the innermost STRONG element, its weight would also be 900, since font-weight can never be higher than 900. Assuming, as we have, that there are only two font faces available, then the text would appear to be either Regular or Bold text, as we see in Figure 5-15:

regular <SPAN> regular <STRONG> bold <B> bold
Figure 5-15

Figure 5-15. Visual weight, with descriptors

5.2.3. Lightening Weights

As you might expect, lighter works in just the same way, except that it causes the user agent to move down the weight scale, instead of up. With a quick modification of the previous example, we can see this very clearly:

/*   assume only two faces for this example: 'Regular' and 'Bold'   */
P {font-weight: 900;}   /* as bold as possible, which will look 'bold' */
P SPAN {font-weight: 700;}   /* this will also be bold */
STRONG {font-weight: lighter;}   /* lighter than its parent */
B {font-weight: lighter;}   /*lighter still */
900 <SPAN> 700 <STRONG> 400 <B> 300 <STRONG> 200
<!-- ...or, to put it another way... -->
bold <SPAN> bold <STRONG> regular <B> regular
<STRONG> regular </STRONG></B></STRONG></SPAN>.

Ignoring the fact that this would be entirely counterintuitive, what we see in Figure 5-16 is that the main paragraph text has a weight of 900 and the SPAN aweight of 700. When the STRONG text is set to lighter, it evaluates to the next-lighter face, which is the regular face, or 400 (the same as normal) on the numeric scale. The next step down is to 300, which comes out the same as normal since no lighter faces exist. From there, the user agent can only reduce the weight one numeric step at a time until it reaches 100 (which it doesn't do in the example). The second paragraph shows which text will be bold, and which regular.

Figure 5-16

Figure 5-16. Making text lighter

Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.

add a background color, as shown in Figure 7-58:

H1 {padding: 10px 0.25em 3ex 3cm; background: silver;}H2 {padding: 0.5em 2em; background: silver;}
Figure 7-58

Figure 7-58. Uneven padding with background colors

As Figure 7-58 demonstrates, thebackground of an element extends into thepadding. As we discussed before, it also extends to the outer edge ofthe border, but the background has to go through the padding beforeit even gets to the border. example, but it was less obvious there because we couldn't see the background then. There is nothing forbidden about this behavior.


In practice, some browsers may not do this correctly. Instead, they will increase the height of a parent element so that the floated element is contained within it, even though this results in a great deal of extra blank space within the parent element.