Ïðèãëàøàåì ïîñåòèòü
Âÿçåìñêèé (vyazemskiy.lit-info.ru)

7.3 Inline Elements

Previous Page Table of Contents Next Page

7.3 Inline Elements

After block-level elements, inline elements are the most common. Setting box properties for inline elements takes us into more interesting territory than we've been so far. Some good examples of inline elements are the em tag and the a tag, both of which are nonreplaced elements, and images, which are replaced elements.

7.3 Inline Elements

Note that none of this applies to table elements. CSS2 introduced new properties and behaviors for handling tables and table content, and these elements behave in ways fairly distinct from either block-level or inline formatting. Table styling is discussed in Chapter 11.


Nonreplaced and replaced elements are treated somewhat differently in the inline context, and we'll look at each in turn as we explore the construction of inline elements.

7.3.1 Line Layout

First, you need to understand how inline content is laid out. It isn't as simple and straightforward as block-level elements, which just generate boxes and usually don't allow anything to coexist with them. By contrast, look inside a block-level element, such as a paragraph. You may well ask, "How did all those lines of text get there? What controls their arrangement? How can I affect it?"

In order to understand how lines are generated, first consider the case of an element containing one very long line of text, as shown in Figure 7-27. Note that you've put a border around the line by wrapping the entire line in a span element and then assigning it a border style:

span {border: 1px dashed black;}
Figure 7-27. A single-line inline element
figs/css2_0727.gif

Figure 7-27 shows the simplest case of an inline element contained by a block-level element. It's no different in its way than a paragraph with two words in it. The only differences are that, in Figure 7-27, you have a few dozen words and most paragraphs don't contain an explicit inline element such as span.

In order to get from this simplified state to something more familiar, all you have to do is determine how wide the element should be, and then break up the line so that the resulting pieces will fit into the width of the element. Therefore, we arrive at the state shown in Figure 7-28.

Figure 7-28. A multiple-line inline element
figs/css2_0728.gif

Nothing has really changed. All you did was take the single line and break it into pieces, and then stack those pieces on top of each other.

In Figure 7-28, the borders for each line of text also happen to coincide with the top and bottom of each line. This is true only because no padding or margin has been set for the inline text. Notice that the borders actually overlap each other slightly; for example, the bottom border of the first line is just below the top border of the second line. This is because the border is actually drawn on the next pixel (assuming you're using a monitor) to the outside of each line. Since the lines are touching each other, their borders will overlap as shown in Figure 7-28.

If you alter the span styles to have a background color, the actual placement of the lines becomes quite clear. Consider Figure 7-29, which contains four paragraphs, each with a different value of text-align and each having the backgrounds of its lines filled in.

Figure 7-29. Showing lines in different alignments
figs/css2_0729.gif

As you can see, not every line reaches to the edge of its parent paragraph's content area, which has been denoted with a dotted gray border. For the left-aligned paragraph, the lines are all pushed flush against the left content edge of the paragraph, and the end of each line happens wherever the line is broken. The reverse is true for the right-aligned paragraph. For the centered paragraph, the centers of the lines are aligned with the center of the paragraph. In the last case, where the value of text-align is justify, each line is forced to be as wide as the paragraph's content area, so that the line's edges touch the content edges of the paragraph. The difference between the natural length of the line and the width of the paragraph is made up by altering the spacing between letters and words in each line. Therefore, the values of letter-spacing and word-spacing can be overridden when text is justified.

That pretty well covers how lines are generated in the simplest cases. As you're about to see, however, the inline formatting model is far from simple.

7.3.2 Basic Terms and Concepts

Before we go any further, let's review some basic terms of inline layout, which will be crucial in navigating the following sections:


Anonymous text

This is any string of characters that is not contained within an inline element. Thus, in the markup <p> I'm <em>so</em> happy!</p>, the sequences " I'm " and " happy!" are anonymous text. Note that the spaces are part of the text since a space is a character like any other.


Em box

This is defined in the given font, otherwise known as the character box. Actual glyphs can be taller or shorter than their em boxes, as discussed in Chapter 5. In CSS, the value of font-size determines the height of each em box.


Content area

In nonreplaced elements, the content area can be one of two things, and the CSS2.1 specification allows user agents to choose which one. The content area can be the box described by the em boxes of every character in the element, strung together, or it can be the box described by the character glyphs in the element. In this book, I use the em box definition for simplicity's sake. In replaced elements, the content area is the intrinsic height of the element plus any margins, borders, or padding.


Leading

The leading is the difference between the values of font-size and line-height. This difference is actually divided in half and is applied to the top and bottom of the content area. These additions to the content area are called, not surprisingly, half-leading. Leading is applied only to nonreplaced elements.


Inline box

This is the box described by the addition of the leading to the content area. For nonreplaced elements, the height of the inline box of an element will be exactly equal to the value for line-height. For replaced elements, the height of the inline box of an element will be exactly equal to the content area since leading is not applied to replaced elements.


Line box

This is the shortest box that bounds the highest and lowest points of the inline boxes that are found in the line. In other words, the top edge of the line box is placed along the top of the highest inline box top, and the bottom of the line box is placed along the bottom of the lowest inline box bottom.

CSS also contains a set of behaviors and useful concepts that fall out of the above list of terms and definitions:

  • The content area is analogous to the content box of a block-level element.

  • The background of an inline element is applied to the content area plus any padding.

  • Any border on an inline element surrounds the content area plus any padding and border.

  • Padding, borders, and margins on nonreplaced elements have no vertical effect on inline elements or the boxes they generate; that is, they do not affect the height of an element's inline box (and thus the line box that contains the element).

  • Margins and borders on replaced elements do affect the height of the inline box for that element and, by implication, the height of the line box for the line that contains the element.

One more thing to note: inline boxes are vertically aligned within the line according to their values for the property vertical-align. I touched on this point in Chapter 6, and this chapter will explain it in more depth.

Before moving on, let's look at a step-by-step process for constructing a line box, which you can use to see how the various pieces of the line fit together to determine its height:

  1. Determine the height of the inline box for each element in the line. This is done by:

    1. Finding the values of font-size and line-height for each inline nonreplaced element and text that is not part of an inline element and adding them together. The leading is split and applied to the top and bottom of the em boxes.

    2. Finding the values of height, margin-top, margin-bottom, padding-top, padding-bottom, border-top-width, and border-top-bottom for each replaced element and adding them together.

  2. Figure out, for each content area, how much of it is above the baseline for the overall line and how much of it is below the baseline. This is not an easy task: you must know the position of the baseline for each element and piece of anonymous text, and the baseline of the line itself, and then line them all up. In addition, the bottom edge of a replaced element sits on the baseline for the overall line.

  3. Determine the vertical offset of any elements that have been given a value for vertical-align. This will tell you how far up or down that element's inline box will be moved and will change how much of the element is above or below the baseline.

  4. Now that you know where all of the inline boxes have come to rest, calculate the final line box height. To do so, just add the distance between the baseline and the highest inline box top to the distance between the baseline and the lowest inline box bottom.

Let's consider the whole process in detail, which is key to intelligently styling inline content.

7.3.3 Inline Formatting

As we discussed in Chapter 6, all elements have a line-height. This value greatly influences the way inline elements are displayed, so let's give it due attention.

First, let's establish how the height of a line is determined. A line's height (or the height of the line box) is determined by the height of its constituent elements and other content, such as text. It's important to understand that line-height actually affects inline elements and other inline content, not block-level elements—at least, not directly. You can set a line-height value for a block-level element, but the value will have visual impact only if it's applied to inline content within that block-level element. Consider the following empty paragraph, for example:

<p style="line-height: 0.25em;"></p>

Without content, the paragraph won't have anything to display—you won't see anything. The fact that this paragraph has a line-height of any value—be it 0.25em or 25in—makes no difference without some content to create a line box.

You can certainly set a line-height value for a block-level element and have that apply to all of the content within the block, whether or not the content is contained in any inline elements. In a certain sense, then, each line of text contained within a block-level element is its own inline element, whether or not it's surrounded by tags. If you like, picture a fictional tag sequence like this:

<p>

<line>This is a paragraph with a number of</line>

<line>lines of text which make up the</line>

<line>contents.</line>

</p>

Even though the line tags don't actually exist, the paragraph behaves as if they did—each line of text inherits styles from the paragraph. Therefore, you only bother to create line-height rules for block-level elements so you don't have to explicitly declare a line-height for all of their inline elements, fictional or otherwise.

The fictional line element actually clarifies the behavior that results from setting line-height on a block-level element. According to the CSS specification, declaring line-height on a block-level element sets a minimum line box height for the content of that block-level element. Thus, declaring p.spacious {line-height: 24pt;} means that the minimum heights for each line box is 24 points. Technically, content can inherit this line height only if an inline element does so. Most text isn't contained by an inline element. Therefore, if you pretend that each line is contained by the fictional line element, the model works out very nicely.

7.3.4 Inline Nonreplaced Elements

Building on your formatting knowledge, let's move on to the construction of lines that contain only nonreplaced elements (or anonymous text). Then, you'll be in a good position to understand the differences between nonreplaced and replaced elements in inline layout.

7.3.4.1 Building the boxes

First, for an inline nonreplaced element or piece of anonymous text, the value of font-size determines the height of the content area. If an inline element has a font-size of 15px, then the content area's height is 15 pixels because all of the em boxes in the element are 15 pixels tall, as illustrated in Figure 7-30.

Figure 7-30. em boxes determine content area height
figs/css2_0730.gif

The next thing to consider is the value of line-height for the element, and the difference between it and the value of font-size. If an inline nonreplaced element has a font-size of 15px and a line-height of 21px, then the difference is 6 pixels. The user agent splits the six pixels in half and applies half to the top and half to the bottom of the content area, which yields the inline box. This process is illustrated in Figure 7-31.

Figure 7-31. Content area plus leading equals inline box
figs/css2_0731.gif

Let's assume that the following is true:

<p style="font-size: 12px; line-height: 12px;">

This is text, <em>some of which is emphasized</em>, plus other text<br>

which is <strong style="font-size: 24px;">strongly emphasized</strong> 

and which is<br>

larger than the surrounding text.

</p>

In this example, most of the text has a font-size of 12px, while the text in one inline nonreplaced element has a size of 24px. However, all of the text has a line-height of 12px since line-height is an inherited property. Therefore, the strong element's line-height is also 12px.

Thus, for each piece of text where both the font-size and line-height are 12px, the content height does not change (since the difference between 12px and 12px is zero), so the inline box is 12 pixels high. For the strong text, however, the difference between line-height and font-size is -12px. This is divided in half to determine the half-leading (-6px), and the half-leading is added to both the top and bottom of the content height to arrive at an inline box. Since you're adding a negative number in both cases, the inline box ends up being 12 pixels tall. The 12-pixel inline box is centered vertically within the 24-pixel content height of the element, so the inline box is actually smaller than the content area.

So far, it sounds like you've done the same thing to each bit of text, and all the inline boxes are the same size, but that's not quite true. The inline boxes in the second line, although they're the same size, don't actually line up because the text is all baseline-aligned (see Figure 7-32).

Figure 7-32. Inline boxes within a line
figs/css2_0732.gif

Since inline boxes determine the height of the overall line box, their placement with respect to each other is critical. The line box is defined as the distance from the top of the highest inline box in the line to the bottom of the lowest inline box, and the top of each line box butts up against the bottom of the line box for the preceding line. The result shown in Figure 7-32 gives you the paragraph shown in Figure 7-33.

Figure 7-33. Line boxes within a paragraph
figs/css2_0733.gif

7.3 Inline Elements

As you can see in Figure 7-33, the middle line is taller than the other two, but it still isn't big enough to contain all of the text within it. The anonymous text's inline box determines the bottom of the line box, while the top of the strong element's inline box sets the top of the line box. Because that inline box's top is inside the element's content area, the contents of the element spill outside the line box, and actually overlap other line boxes. The result is that the lines of text look irregular. Later in the chapter, we'll explore ways to cope with this behavior and methods for achieving consistent baseline spacing.


7.3.4.2 Vertical alignment

If you change the vertical alignment of the inline boxes, the same height determination principles apply. Suppose that you give the strong element a vertical alignment of 4px:

<p style="font-size: 12px; line-height: 12px;">

This is text, <em>some of which is emphasized</em>, plus other text<br>

that is <strong style="font-size: 24px; vertical-align: 4px;">strongly 

emphasized</strong> and that is<br>

larger than the surrounding text.

</p>

That small change raises the element four pixels, which pushes up both its content area and its inline box. Because the strong element's inline box top was already the highest in the line, this change in vertical alignment also pushes the top of the line box upward by four pixels, as shown in Figure 7-34.

Figure 7-34. Vertical alignment affects line box height
figs/css2_0734.gif

Let's consider another situation. Here, you have another inline element in the same line as the strong text, and its alignment is other than the baseline:

<p style="font-size: 12px; line-height: 12px;">

this is text, <em>some of which is emphasized</em>, plus other text<br>

that is <strong style="font-size: 24px;">strong</strong> 

and <span style="vertical-align: top;">tall</span> and that is<br>

larger than the surrounding text.

</p>

Now you have the same result as in your earlier example, where the middle line box is taller than the other line boxes. However, notice how the "tall" text is aligned in Figure 7-35.

Figure 7-35. Aligning an inline element to the line box
figs/css2_0735.gif

In this case, the top of the "tall" text's inline box is aligned with the top of the line box. Since the "tall" text has equal values for font-size and line-height, the content height and inline box are the same. However, consider this:

<p style="font-size: 12px; line-height: 12px;">

This is text, <em>some of which is emphasized</em>, plus other text<br>

that is <strong style="font-size: 24px;">strong</strong> 

and <span style="vertical-align: top; line-height: 4px;">tall</span> 

and that is<br>

larger than the surrounding text.

</p>

Since the line-height for the "tall" text is less than its font-size, the inline box for that element is smaller than its content area. This fact changes the placement of the text itself since the top of its inline box must be aligned with the top of the line box for its line. Thus, you get the result shown in Figure 7-36.

Figure 7-36. Text protruding from the line box (again)
figs/css2_0736.gif

On the other hand, you could set the "tall" text to have a line-height that is actually bigger than its font-size. For example:

<p style="font-size: 12px; line-height: 12px;">

This is text, <em>some of which is emphasized</em>, plus other text<br>

that is <strong style="font-size: 24px;">strong</strong> 

and <span style="vertical-align: top; line-height: 18px;">tall</span> 

and that is<br>

larger than the surrounding text.

</p>

Since you've given the "tall" text a line-height of 18px, the difference between line-height and font-size is 6 pixels. The half-leading of 3 pixels is added to the content area and results in an inline box that is 18 pixels tall. The top of this inline box aligns with the top of the line box. Similarly, the value bottom will align the bottom of an inline element's inline box with the bottom of the line box.

In the terms we've been using in this chapter, the effects of the assorted keyword values of vertical-align are:


top

Aligns the top of the element's inline box with the top of the containing line box.


bottom

Aligns the bottom of the element's inline box with the bottom of the containing line box.


text-top

Aligns the top of the element's inline box with the top of the parent's content area.


text-bottom

Aligns the bottom of the element's inline box with the bottom of the parent's content area.


middle

Aligns the vertical midpoint of the element's inline box with a point one-half ex above the baseline of the parent.


super

Moves the content area and inline box of the element upward. The distance is not specified and may vary by user agent.


sub

The same as super, except the element is moved downward instead of upward.


<percentage>

Shifts the element up or down the distance defined by taking the declared percentage of the element's value for line-height.

These values are explained in more detail in Chapter 6.

7.3.4.3 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 in order to keep content from overlapping?

One way to do this 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;}



<p>

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

contains a line in which </span><big>some big text </big><span>is found.<br>

This large text helps illustrate our point.

</p>

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
figs/css2_0737.gif

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 5-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
figs/css2_0738.gif

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 x 1.5 x 1.5), and that will also be the height of the line box. In order 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 each other. 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.


7.3.4.4 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 a computed, value. Let's say you want the line-height of all elements in a document to be one-and-one-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%;}



<p>This paragraph has a line-height of 1.5 times its font-size. In addition,

any elements within it <small>such as this small element</small> also have

line-heights 1.5 times their font-size...and that includes <big>this big 

element right here</big>. By using a scaling factor, line-heights scale

to match the font-size of any element.</p>
Figure 7-39. Using a scaling factor for line-height
figs/css2_0739.gif

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 in keeping 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 will mean the absolute minimum size necessary is used to contain the content area of each element.

7.3 Inline Elements

Most fonts still display a little bit of space between the lines of character glyphs because characters are usually smaller than their em boxes.


7.3.4.5 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
figs/css2_0740.gif

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, and 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
figs/css2_0741.gif

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

7.3 Inline Elements

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
figs/css2_0742.gif

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 lines' backgrounds 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 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 is a background color. Thus, you get the result shown in Figure 7-43.

Figure 7-43. Overlapping inline backgrounds
figs/css2_0743.gif

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 shows you. 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 keep inline nonreplaced element backgrounds from overlapping, it can still happen, depending on which font is in use. 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 will not be possible with CSS.


7.3.5 Inline Replaced Elements

Inline replaced elements, such as images, are assumed to have an intrinsic height and width; for example, an image will be a certain number of pixels high and wide. Therefore, a replaced element with an intrinsic height can cause a line box to become taller than normal. This does not change the value of line-height for any element in the line, including the replaced element itself. Instead, the line box is simply made tall enough to accommodate the replaced element, plus any box properties. In other words, the entirety of the replaced element—content, margins, borders, and padding—is used to define the element's inline box. The following styles lead to one such example, as shown in Figure 7-44:

p {font-size: 15px; line-height: 18px;}

img {height: 30px; margin: 0; padding: 0; border: none;}
Figure 7-44. Replaced elements can increase the height of the line box but not the value of line-height
figs/css2_0744.gif

Despite all the blank space, the effective value of line-height has not changed, either for the paragraph or the image itself. line-height simply has no effect on the image's inline box. Because the image in Figure 7-44 has no padding, margins, or borders, its inline box is equivalent to its content area, which is, in this case, 30 pixels tall.

Nonetheless, an inline replaced element still has a value for line-height. Why? In the most common case, it needs the value in order to correctly position the element if it's been vertically aligned. Recall that, for example, percentage values for vertical-align are calculated with respect to an element's line-height. Thus:

p {font-size: 15px; line-height: 18px;}

img {vertical-align: 50%;}



<p>The image in this sentence <imgsrc="test.gif" alt="test image"> 

will be raised 9 pixels.</p>

The inherited value of line-height causes the image to be raised nine pixels instead of some other number. Without a value for line-height, it wouldn't be possible to perform percentage-value vertical alignments. The height of the image itself has no relevance when it comes to vertical alignment: the value of line-height is all that matters.

However, for other replaced elements, it might be important to pass on a line-height value to descendant elements within that replaced element. An example would be an SVG image, which uses CSS to style any text found within the image.

7.3.5.1 Adding box properties

After everything else, applying margins, borders, and padding to inline replaced elements almost seems simple.

Padding and borders are applied to replaced elements as usual; padding inserts space around the actual content and the border surrounds the padding. What's unusual about the process is that these two things actually influence the height of the line box because they are part of the inline box of an inline replaced element (unlike inline nonreplaced elements). Consider Figure 7-45, which results from the following styles:

img {height: 20px; width: 20px;}

img.one {margin: 0; padding: 0; border: 1px dotted;}

img.two {margin: 5px; padding: 3px; border: 1px solid;}
Figure 7-45. Adding padding, borders, and margins to an inline replaced element increases its inline box
figs/css2_0745.gif

Note that the first line box is made tall enough to contain the image, whereas the second is tall enough to contain the image, its padding, and its border.

Margins are also contained within the line box, but they have their own wrinkles. Setting a positive margin is no mystery; it will simply make the inline box of the replaced element taller. Setting negative margins, meanwhile, has a similar effect: it decreases the size of the replaced element's inline box. This is illustrated in Figure 7-46, where you can see that a negative top margin is pulling down the line above the image:

img.two {margin-top: -10px;}
Figure 7-46. The effect of negative margins on inline replaced elements
figs/css2_0746.gif

Negative margins operate the same way on block-level elements, of course. In this case, the negative margins make the replaced element's inline box smaller than ordinary. Negative margins are the only way to cause inline replaced elements to bleed into other lines.

7.3.5.2 Replaced elements and the baseline

You may have noticed by now that, by default, inline replaced elements sit on the baseline. If you add bottom padding, a margin, or a border to the replaced element, then the content area will move upward. Replaced elements do not actually have baselines of their own, so the next best thing is to align the bottom of their inline boxes with the baseline. Thus, it is actually the bottom outer margin edge that is aligned with the baseline, as illustrated in Figure 7-47.

Figure 7-47. Inline replaced elements sit on the baseline
figs/css2_0747.gif

This baseline alignment leads to an unexpected (and unwelcome) consequence: an image placed in a table cell all by itself should make the table cell tall enough to contain the line box containing the image. The resizing occurs even if there is no actual text, not even whitespace, in the table cell with the image. Therefore, the common sliced-image and spacer-GIF designs of years past can fall apart quite dramatically in modern browsers. Consider the simplest case:

td {font-size: 12px;}



<td><img src="spacer.gif" height="1" width="10"></td>

Under the CSS inline formatting model, the table cell will be 12 pixels tall, with the image sitting on the baseline of the cell. So there might be three pixels of space below the image, and eight above it, although the exact distances would depend on the font family used and the placement of its baseline. This behavior is not confined to images inside table cells; it will also happen in any situation where an inline replaced element is the sole descendant of a block-level or table-cell element. For example, an image inside a div will also sit on the baseline.

7.3 Inline Elements

As of this writing, many browsers actually ignore this CSS inline formatting model, but Gecko-based browsers act as the text describes when rendering XHTML and strict HTML documents. See my article "Images, Tables, and Mysterious Gaps" at http://devedge.netscape.com/viewsource/2002/img-table/ for more information.


The most common workaround for such circumstances is simply to make spacer images block-level, so that they do not generate a line box. For example:

td {font-size: 12px;}

img.block {display: block;}



<td><img src="spacer.gif" height="1" width="10" class="block"></td>

Another possible fix would be to make the font-size and line-height of the enclosing table cell 1px, which would make the line box only as tall as the 1-pixel image within it.

Here's another interesting effect of inline replaced elements sitting on the baseline: if you apply a negative bottom margin, the element will actually get pulled downward because the bottom of its inline box will be higher than the bottom of its content area. Thus, the following rule would have the result shown in Figure 7-48:

p img {margin-bottom: -10px;}
Figure 7-48. Pulling inline replaced elements down with a negative bottom margin
figs/css2_0748.gif

This can easily cause a replaced element to bleed into following lines of text, as Figure 7-48 shows.

7.3 Inline Elements

Some browsers simply place the bottom of the content area on the baseline and ignore any negative bottom margin.


Inline with History

The CSS inline formatting model may seem needlessly complex and, in some ways, even contrary to author expectations. Unfortunately, the complexity is the result of creating a style language that is both backward-compatible with pre-CSS web browsers and also leaves the door open for future expansion into more sophisticated territory—an awkward blend of past and present. It's also the result of making some sensible decisions that avoid one undesirable effect while causing another.

For example, the "spreading apart" of lines of text by image and vertically aligned text owes its roots to the way Mosaic 1.0 behaved. In that browser, any image in a paragraph would simply push open enough space to contain the image. That's a good behavior, since it prevents images from overlapping text in other lines. So when CSS introduced ways to style text and inline elements, its authors endeavored to create a model that did not (by default) cause inline images to overlap other lines of text. However, the same model also meant that a superscript element (sup), for example, would likely also push apart lines of text.

Such effects annoy some authors who want their baselines to be an exact distance apart and no further, but consider the alternative. If line-height forced baselines to be exactly a specified distance apart, you'd easily end up with inline replaced and vertically shifted elements that overlap other lines of text—which would also annoy authors. Fortunately, CSS offers enough power to create your desired effect in one way or another, and the future of CSS holds even more potential.


    Previous Page Table of Contents Next Page