< Day Day Up > |
7.3 Inline ElementsAfter 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.
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 LayoutFirst, 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 elementFigure 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 elementNothing 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 alignmentsAs 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 ConceptsBefore we go any further, let's review some basic terms of inline layout, which will be crucial in navigating the following sections:
CSS also contains a set of behaviors and useful concepts that fall out of the above list of terms and definitions:
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:
Let's consider the whole process in detail, which is key to intelligently styling inline content. 7.3.3 Inline FormattingAs 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 ElementsBuilding 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 boxesFirst, 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 heightThe 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 boxLet'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 lineSince 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
7.3.4.2 Vertical alignmentIf 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 heightLet'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 boxIn 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)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:
These values are explained in more detail in Chapter 6. 7.3.4.3 Managing the line-heightIn 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 elementsNote 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 bordersThis 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.
7.3.4.4 Scaling line heightsThe 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-heightIn 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.4.5 Adding box propertiesAs 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 layoutThe 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 heightAs 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.
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 elementThink 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 backgroundsCSS 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.
7.3.5 Inline Replaced ElementsInline 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-heightDespite 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 propertiesAfter 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 boxNote 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 elementsNegative 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 baselineYou 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 baselineThis 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.
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 marginThis can easily cause a replaced element to bleed into following lines of text, as Figure 7-48 shows.
|
< Day Day Up > |