CSS: The Definitive Guide, 3rd Edition (29 page)

Read CSS: The Definitive Guide, 3rd Edition Online

Authors: Eric A. Meyer

Tags: #COMPUTERS / Web / Page Design

BOOK: CSS: The Definitive Guide, 3rd Edition
9.15Mb size Format: txt, pdf, ePub
Managing the
line-height

In
previous sections, you saw that changing the
line-height
of an inline element can cause text from one line to
overlap another. In each case, though, the changes were made to individual
elements. So how can you affect the
line-height
of elements in a more general way to prevent content from
overlapping?

One way is to use the em unit in conjunction with an
element whose
font-size
has changed. For
example:

p {font-size: 14px; line-height: 1em;}
big {font-size: 250%; line-height: 1em;}


Not only does this paragraph have "normal" text, but it also

contains a line in which some big text is found.

This large text helps illustrate our point.


By
setting a
line-height
for the
big
element, you increase the overall height of the
line box, providing enough room to display the
big
element without overlapping any other text and without changing the
line-height
of all lines in the paragraph.
You use a value of
1em
so that the
line-height
for the
big
element will be set to the same size as
big
's
font-size
. Remember,
line-height
is set in relation to the
font-size
of the element itself, not the
parent element. The results are shown in
Figure 7-37
.

Figure 7-37. Assigning the line-height property to inline elements

Note that the following styles can produce the same result as in
Figure
7-37
:

p {font-size: 14px; line-height: 1;}
big {font-size: 250%;}

Unless
line-height
values are inherited as scaling
factors, both the
p
and
big
elements would have a
line-height
of
1
. Thus, the
height of the inline box would match the height of the content area, just as in
Figure 7-37
.

Make sure
you really understand the previous sections because things will get trickier when
you try to add borders. Let's say you want to put five-pixel borders around any
hyperlink:

a:link {border: 5px solid blue;}

If
you don't set a large enough
line-height
to
accommodate the border, it will be in danger of overwriting other lines. You could
increase the size of the inline box for unvisited links using
line-height
, as you did for the
big
element in the earlier example; in this case,
you'd just need to make the value of
line-height
10 pixels larger than the value of
font-size
for those links. However, that could be difficult if you
don't actually know the size of the font in pixels.

Another solution
is to increase the
line-height
of the
paragraph. This will affect every line in the entire element, not just the line in
which the bordered hyperlink
appears:

p {font-size: 14px; line-height: 24px;}
a:link {border: 5px solid blue;}

Because
there is extra space added above and below each line, the border around the
hyperlink doesn't impinge on any other line, as you can see in
Figure 7-38
.

Figure 7-38. Increasing line-height to leave room for inline borders

This approach works here, of course, because all of the text is the
same size. If there were other elements in the line that changed the height of the
line box, your border situation might also change. Consider the
following:

p {font-size: 14px; line-height: 24px;}
a:link {border: 5px solid blue;}
big {font-size: 150%; line-height: 1.5em;}

Given
these rules, the height of the inline box of a
big
element within a paragraph will be 31.5 pixels (14 × 1.5 × 1.5),
and that will also be the height of the line box. To keep baseline spacing
consistent, you must make the
p
element's
line-height
equal to or greater than
32px
.

Baselines and Line Heights

The actual height of each line box depends on the way its component elements
line up with one another. This alignment tends to depend very much on where the
baseline falls within each element (or piece of anonymous text) because that
location determines how their inline boxes are arranged. The placement of the
baseline within each em box is different for every font. This information is
built into the font files and cannot be altered by any means other than
directly editing the font files.

Thus, consistent baseline spacing tends to be more of an art than a science.
If you declare all of your font sizes and line heights using a single unit,
such as ems, then you have a reliable chance of consistent baseline spacing. If
you mix units, however, that feat becomes a great deal more difficult, if not
impossible. As of this writing, there are proposals for properties that would
let authors enforce consistent baseline spacing regardless of the inline
content, which would greatly simplify certain aspects of online typography.
None of these proposed properties have been implemented, though, which makes
their adoption a distant hope at best.

Scaling line heights

The best way to set
line-height
, as it turns
out, is to use a raw number as the value. This method is the best because the
number becomes the scaling factor, and that factor is an inherited, not computed,
value. Let's say you want the
line-height
of
all elements in a document to be one-and-a-half times their
font-size
. You would declare:

body {line-height: 1.5;}

This scaling factor of
1.5
is passed down
from element to element, and, at each level, the factor is used as a multiplier of
the
font-size
of each element. Therefore, the
following markup would be displayed as shown in
Figure 7-39
:

p {font-size: 15px; line-height: 1.5;}
small {font-size: 66%;}
big {font-size: 200%;}

This paragraph has a line-height of 1.5 times its font-size. In addition,
any elements within it such as this small element also have
line-heights 1.5 times their font-size...and that includes this big
element right here
. By using a scaling factor, line-heights scale
to match the font-size of any element.


Figure 7-39. Using a scaling
factor for line-height

In this example, the line height for the
small
element turns out to be
15px
,
and for the
big
element, it's
45px
. (These numbers may seem excessive, but they're
consistent with the overall page design.) Of course, if you don't want your
big
text to generate too much extra leading,
you can give it a
line-height
value, which will
override the inherited scaling factor:

p {font-size: 15px; line-height: 1.5;}
small {font-size: 66%;}
big {font-size: 200%; line-height: 1em;}

Another solution—possibly the simplest of all—is to set the styles such that
lines are no taller than absolutely necessary to hold their content. This is where
you might use a
line-height
of
1.0
. This value will multiply itself by every
font-size
to get the same value as the
font-size
of every element. Thus, for every
element, the inline box will be the same as the content area, which means the
absolute minimum size necessary is used to contain the content area of each
element.

Tip

Most fonts still display a little bit of space between the lines of
character glyphs because characters are usually smaller than their em boxes.
The exception is script ("cursive") fonts, where character glyphs are usually
larger
than their em boxes.

Adding box
properties

As you're aware from previous discussions,
padding, margins, and borders may all be applied to inline nonreplaced elements.
These aspects of the inline element do not influence the height of the line box at
all. If you were to apply some borders to a
span
element without any margins or padding, you'd get results such as
those shown in
Figure
7-40
.

Figure 7-40. Inline borders and line-box layout

The border edge of inline elements is controlled by the
font-size
, not the
line-height
. In other words, if a
span
element has a
font-size
of
12px
and a
line-height
of
36px
, its content
area is
12px
high, and the border will surround
that content area.

Alternatively, you can assign padding to the inline
element, which will push the borders away from the text
itself:

span {border: 1px solid black; padding: 4px;}

Note
that this padding does not alter the actual shape of the content height, so it
will not affect the height of the inline box for this element. Similarly, adding
borders to an inline element will not affect the way line boxes are generated and
laid out, as illustrated in
Figure
7-41
.

Figure 7-41. Padding and borders do not alter line height

As for margins, they do not, practically speaking, apply to the top
and bottom of an inline non-replaced element, as they don't affect the height of
the line box. The ends of the element are another story.

Tip

CSS2.1 actually makes margin placement
explicit: it defines
margin-top
and
margin-bottom
as applying to all elements except inline nonreplaced elements, instead of
simply saying that user agents should ignore top and bottom margins.

Recall the idea that an inline element is basically laid out as a single
line and then broken up into pieces. So, if you apply margins to an inline
element, those margins will appear at its beginning and end; these are the left
and right margins, respectively. Padding also appears at the edges. Thus, although
padding and margins (and borders) do not affect line heights, they can still
affect the layout of an element's content by pushing text away from its ends. In
fact, negative left and right margins can pull text closer to the inline element,
or even cause overlap, as
Figure 7-42
shows.

Figure 7-42. Padding and margins on the ends of an inline element

Think of an inline element as a strip of paper with some plastic
surrounding it. Displaying the inline element on multiple lines is like cutting up
the strip into smaller strips. However, no extra plastic is added to each smaller
strip. The only plastic is that which was on the strip to begin with, so it
appears only at the beginning and end of the original ends of the paper strip (the
inline element).

So, what happens when an inline element has a
background and enough padding to cause the backgrounds of the lines to overlap?
Take the following situation as an
example:

p {font-size: 15px; line-height: 1em;}
p span {background: #999; padding-top: 10px; padding-bottom: 10px;}

All
of the text within the
span
element will have a
content area that is 15 pixels tall, and you've applied 10 pixels of padding to
the top and bottom of each content area. The extra pixels won't increase the
height of the line box, which would be fine, except there's a background color.
Thus, you get the result shown in
Figure
7-43
.

Figure 7-43. Overlapping inline backgrounds

CSS 2.1 explicitly states that the line boxes are drawn in document
order: "This will cause the borders on subsequent lines to paint over the borders
and text of previous lines." The same principle applies to backgrounds as well, as
Figure 7-43
demonstrates. CSS2, on
the other hand, allowed user agents "to 'clip' the border and padding areas (i.e.,
not render them)." Therefore, the results may depend greatly on which
specification the user agent follows.

Glyphs Versus Content Area

Even in cases where you try to prevent inline
nonreplaced
element backgrounds from overlapping, it can still happen, depending on which
font is used. The problem lies in the difference between a font's em box and
its character glyphs. Most fonts, as it turns out, don't have em boxes whose
heights match the character glyphs.

That may sound very abstract, but it has practical consequences. In CSS2.1,
we find the following: "The height of the content area should be based on the
font, but this specification does not specify how. A user agent may...use the
em box or the maximum ascender and descender of the font. (The latter would
ensure that glyphs with parts above or below the em box still fall within the
content area, but leads to differently sized boxes for different fonts.)"

In other words, the "painting area" of an inline nonreplaced element is left
to the user agent. If a user agent takes the em box to be the height of the
content area, then the background of an inline nonreplaced element will be
equal to the height of the em box (which is the value of
font-size
). If a user agent uses the maximum
ascender and descender of the font, then the background may be taller or
shorter than the em box. Therefore, you could give an inline nonreplaced
element a
line-height
of
1em
and still have its background overlap the
content of other lines.

There is no way to prevent this overlap in CSS2 or CSS2.1, but there are
properties proposed for CSS3 that would let the author control the behavior of
the user agent. Until these properties are widely implemented, truly precise
typography is not possible with CSS.

Other books

Red Joan by Jennie Rooney
Masquerade by Gayle Lynds
They call her Dana by Wilde, Jennifer
Krac's Firebrand by S. E. Smith
The Playboy of Rome by Jennifer Faye
The Abduction by James Grippando
Turn It Up by Arend, Vivian
Titan by Stephen Baxter
The Gathering by Lily Graison