< Day Day Up > |
10.1 FloatingYou are almost certainly acquainted with the concept of floated elements. Ever since Netscape 1, it has been possible to float images by declaring, for instance, <img src="b5.gif" align="right">. This causes an image to float to the right and allows other content (such as text) to "flow around" the image. The name "floating," in fact, comes from the document "Extensions to HTML 2.0," which stated:
In the past, it was only possible to float images and, in some browsers, tables. CSS, on the other hand, lets you float any element, from images to paragraphs to lists. In CSS, this behavior is accomplished using the property float.
For example, to float an image to the left, you could use this markup: <img src="b4.gif" style="float: left;" alt="b4"> As Figure 10-1 makes clear, the image "floats" to the left side of the browser window and the text flows around it. This is just what you should expect. Figure 10-1. A floating imageHowever, when floating elements in CSS, some interesting issues come up. 10.1.1 Floated ElementsKeep a few things in mind with regard to floating elements. In the first place, a floated element is, in some ways, removed from the normal flow of the document, although it still affects the layout. In a manner utterly unique within CSS, floated elements exist almost on their own plane, yet they still have influence over the rest of the document. This influence derives from the fact that when an element is floated, other content "flows around" it. This is familiar behavior with floated images, but the same is true if you float a paragraph, for example. In Figure 10-2, you can see this effect quite clearly, thanks to the margin added to the floated paragraph: p.aside {float: right; width: 15em; margin: 0 1em 1em; padding: 0.25em; border: 1px solid;} Figure 10-2. A floating paragraphOne of the first interesting things to notice about floated elements is that margins around floated elements do not collapse. If you float an image with 20-pixel margins, there will be at least 20 pixels of space around that image. If other elements adjacent to the image—and that means adjacent horizontally and vertically—also have margins, those margins will not collapse with the margins on the floated image, as you can see in Figure 10-3: p img {float: left; margin: 25px;} Figure 10-3. Floating images with marginsTo resurrect the paper-and-plastic analogy from Chapter 7, the plastic margins around an image never overlap the plastic surrounding other floated elements. If you do float a nonreplaced element, you must declare a width for that element. Otherwise, according to the CSS specification, the element's width will tend toward zero. Thus, a floated paragraph could literally be one character wide, assuming one character is the browser's minimum value for width. If you fail to declare a width value for your floated elements, you could end up with something like Figure 10-4. (It's unlikely, granted, but still possible.) Figure 10-4. Floated text without an explicit width10.1.1.1 No floating at allThere is one other value for float besides left and right. float: none is used to prevent an element from floating at all. This might seem a little silly, since the easiest way to keep an element from floating is to simply avoid declaring a float, right? Well, first of all, the default value of float is none. In other words, the value has to exist in order for normal, nonfloating behavior to be possible; without it, all elements would float in one way or another. Second, you might want to override a certain style from an imported style sheet. Imagine that you're using a server-wide style sheet that floats images. On one particular page, you don't want those images to float. Rather than writing a whole new style sheet, you could simply place img {float: none;} in your document's embedded style sheet. Beyond this type of circumstance, though, there really isn't much call to actually use float: none. 10.1.2 Floating: The DetailsBefore we start digging into details of floating, it's important to establish the concept of a containing block. A floated element's containing block is the nearest block-level ancestor element. Therefore, in the following markup, the floated element's containing block is the paragraph element that contains it: <h1>Test</h1> <p> This is paragraph text, but you knew that. Within the content of this paragraph is an image that's been floated. <img src="testy.gif" style="float: right;"> The containing block for the floated image is the paragraph. </p>
Furthermore, a floated element generates a block box, regardless of the kind of element it is. Thus, if you float a link, even though the element is inline and would ordinarily generate an inline box, it generates a block box when floated. It will be laid out and act as if it was, for example, a div. This is not unlike declaring display: block for the floated element, although it is not necessary to do so. A series of specific rules govern the placement of a floated element, so let's cover those before digging into applied behavior. These rules are vaguely similar to those that govern the evaluation of margins and widths and have the same initial appearance of common sense. They are as follows:
Figure 10-5. Floating to the left (or right)
Figure 10-6. Keeping floats from overlapping
Figure 10-7. More overlap prevention
Figure 10-8. Unlike balloons, floated elements can't float upward
Figure 10-9. Keeping floats below their predecessors
Figure 10-10. Keeping floats level with their context
Figure 10-11. If there isn't room, floats get pushed to a new "line"
Figure 10-12. Given the other constraints, go as high as possible
Figure 10-13. Get as far to the left (or right) as possible10.1.3 Applied BehaviorThere are a number of interesting consequences that fall out of the rules we've just seen, both because of what they say and what they don't say. The first thing to discuss is what happens when the floated element is taller than its parent element. This happens quite often, as a matter of fact. Take the example of a short document, composed of no more than a few paragraphs and h3 elements, where the first paragraph contains a floated image. Further, this floated image has a margin of five pixels (5px). You would expect the document to be rendered as shown in Figure 10-14. Figure 10-14. Expected floating behaviorNothing there is unusual, of course, but Figure 10-15 shows what happens when you set the first paragraph to have a background. Figure 10-15. Backgrounds and floated elementsThere is nothing different about the second example, except for the visible background. As you can see, the floated image sticks out of the bottom of its parent element. Of course, it did so in the first example, but it was less obvious there because you couldn't see the background. The floating rules we discussed earlier address only the left, right, and top edges of floats and their parents. The deliberate omission of bottom edges requires the behavior in Figure 10-15.
CSS2.1 clarified one aspect of floated-element behavior, which is that a floated element will expand to contain any floated descendants. (Previous versions of CSS were unclear about what should happen.) Thus, you could contain a float within its parent element by floating the parent, as in this example: <div style="float: left; width: 100%;"> <img src="hay.gif" style="float: left;"> The 'div' will stretch around the floated image because the 'div' has been floated. </div> On a related note, consider backgrounds and their relationship to floated elements that occur earlier in the document, which is illustrated in Figure 10-16. Figure 10-16. Element backgrounds "slide under" floated elementsBecause the floated element is both within and outside of the flow, this sort of thing is bound to happen. What's going on? The content of the heading is being "displaced" by the floated element. However, the heading's element width is still as wide as its parent element. Therefore, its content area spans the width of the parent and so does the background. The actual content doesn't flow all the way across its own content area so that it can avoid being obscured behind the floating element. 10.1.3.1 Negative marginsInterestingly, negative margins can cause floated elements to move outside of their parent elements. This seems to be in direct contradiction to the rules explained earlier, but it isn't. In the same way that elements can appear to be wider than their parents through negative margins, floated elements can appear to protrude out of their parents. Let's consider a floated image that is floated to the left, and that has left and top margins of -15px. This image is placed inside a div that has no padding, borders, or margins. The result is shown in Figure 10-17. Figure 10-17. Floating with negative marginsContrary to appearances, this does not violate the restrictions on floated elements being placed outside their parent elements. Here's the technicality that permits this behavior: a close reading of the rules in the previous section will show that the outer edges of a floating element must be within the element's parent. However, negative margins can place the floated element's content such that it effectively overlaps its own outer edge, as detailed in Figure 10-18. Figure 10-18. The details of floating up and left with negative marginsThe math situation works out something like this: assume the top inner edge of the div is at the pixel position 100. The browser, in order to figure out where the top inner edge of the floated element should be, will do this: 100px + (-15px) margin + 0 padding = 85px. Thus, the top inner edge of the floated element should be at pixel position 85; even though this is higher than the top inner edge of the float's parent element, the math works out such that the specification isn't violated. A similar line of reasoning explains how the left inner edge of the floated element can be placed to the left of the left inner edge of its parent. Many of you may have an overwhelming desire to cry "Foul!" right about now. Personally, I don't blame you. It seems completely wrong to allow the top inner edge to be higher than the top outer edge, for example, but with a negative top margin, that's exactly what you get—just as negative margins on normal, nonfloated elements can make them visually wider than their parents. The same is true on all four sides of a floated element's box: set the margins to be negative, and the content will overrun the outer edge without technically violating the specification. There is one important question here: what happens to the document display when an element is floated out of its parent element by using negative margins? For example, an image could be floated so far up that it intrudes into a paragraph that has already been displayed by the user agent. In such a case, it's up to the user agent to decide whether the document should be reflowed. The CSS1 and CSS2 specifications explicitly state that user agents are not required to reflow previous content to accommodate things that happen later in the document. In other words, if an image is floated up into a previous paragraph, it may simply overwrite whatever was already there. On the other hand, the user agent may handle the situation by flowing content around the float. Either way, it's probably a bad idea to count on a particular behavior, which makes the utility of negative margins on floats somewhat limited. Hanging floats are probably fairly safe, but trying to push an element upward on the page is generally a bad idea. There is one other way for a floated element to exceed its parent's inner left and right edges, and that's when the floated element is wider than its parent. In that case, the floated element will simply overflow the right or left inner edge—depending on which way the element is floated—in its best attempt to display itself correctly. This will lead to a result like that shown in Figure 10-19. Figure 10-19. Floating an element that is wider than its parent10.1.4 Floats, Content, and OverlappingAn even more interesting question is this: what happens when a float overlaps content in the normal flow? This can happen if, for example, a float has a negative margin on the side where content is flowing past (e.g., a negative left margin on a right-floating element). You've already seen what happens to the borders and backgrounds of block-level elements. What about inline elements? CSS1 and CSS2 were not completely clear about the expected behavior in such cases. CSS2.1 clarified the subject with explicit rules. These state that:
To illustrate these rules, consider the following situation: <img src="testy.gif" class="sideline"> <p class="box"> This paragraph, unremarkable in most ways, does contain an inline element. This inline contains some <strong>strongly emphasized text, which is so marked to make an important point</strong>. The rest of the element's content is normal anonymous inline content. </p> <p> This is a second paragraph. There's nothing remarkable about it, really. Please move along. </p> <h2 id="jump-up">A Heading!</h2> To that markup, apply the following styles, with the result seen in Figure 10-20: img.sideline {float: left; margin: 10px -15px 10px 10px;} p.box {border: 1px solid gray; padding: 0.5em;} p.box strong {border: 3px double black; background: silver; padding: 2px;} h2#jump-up {margin-top: -15px; background: silver;} Figure 10-20. Layout behavior when overlapping floatsThe inline element (strong) completely overlaps the floated image—background, border, content, and all. The block elements, on the other hand, have only their content appear on top of the float. Their backgrounds and borders are placed behind the float.
10.1.5 ClearingWe've talked quite a bit about floating behavior, so there's only one more thing to discuss before we turn to positioning. You won't always want your content to flow past a floated element—in some cases, you'll specifically want to prevent it. If you have a document that is grouped into sections, you might not want the floated elements from one section hanging down into the next. In that case, you'd want to set the first element of each section to prohibit floating elements from appearing next to it. If the first element might otherwise be placed next to a floated element, it will be pushed down until it appears below the floated image, and all subsequent content will appear after that, as shown in Figure 10-21. Figure 10-21. Displaying an element in the clearThis is done with clear.
For example, to make sure all h3 elements are not placed to the right of left-floating elements, you would declare h3 {clear: left;}. This can be translated as "make sure that the left side of an h3 is clear of floating images," and is equivalent to the HTML construct <br clear="left">. The following rule uses clear to prevent h3 elements from flowing past floated elements to the left side: h3 {clear: left;} While this will push the h3 past any left-floating elements, it will allow floated elements to appear on the right side of h3 elements, as shown in Figure 10-22. Figure 10-22. Clear to the left, but not the rightIn order to avoid this sort of thing, and to make sure that h3 elements do not coexist on a line with any floated elements, you use the value both: h3 {clear: both;} Understandably enough, this value prevents coexistence with floated elements on both sides of the cleared element, as demonstrated in Figure 10-23. Figure 10-23. Clear on both sidesIf, on the other hand, we were only worried about h3 elements being pushed down past floated elements to their right, then you'd use h3 {clear: right;}. Finally, there's clear: none, which allows elements to float to either side of an element. As with float: none, this value mostly exists to allow for normal document behavior, in which elements will permit floated elements to both sides. none can be used to override other styles, of course, as shown in Figure 10-24. Despite the document-wide rule that h3 elements will not permit floated elements to either side, one h3 in particular has been set so that it does permit floated elements on either side: h3 {clear: both;} <h3 style="clear: none;">What's With All The Latin?</h3> Figure 10-24. Not clear at allIn CSS1 and CSS2, clear worked by increasing the top margin of an element so that it ended up below a floated element, so any margin width set for the top of a cleared element was effectively ignored. That is, instead of being 1.5em, for example, it would be increased to 10em, or 25px, or 7.133in, or however much was needed to move the element down far enough so that the content area is below the bottom edge of a floated element. In CSS2.1, clearance was introduced. Clearance is extra spacing added above an element's top margin in order to push it past any floated elements. This means that the top margin of a cleared element does not change when an element is cleared. It's downward movement is caused by the clearance instead. Pay close attention to the placement of the heading's border in Figure 10-25, which results from the following: img.sider {float: left; margin: 0;} h3 {border: 1px solid gray; clear: left; margin-top: 15px;} <img src="boxer.gif" class="sider" height="50" width="50"> <img src="stripe.gif" height="10" width="100"> <h3>Why Doubt Salmon?</h3> Figure 10-25. Clearing and its effect on marginsThere is no separation between the top border of the h3 and the bottom border of the floated image because 25 pixels of clearance were added above the 15-pixel top margin in order to push the h3's top border edge just past the bottom edge of the float. This will be the case unless the h3's top margin calculates to 40 pixels or more, in which case the h3 will naturally place itself below the float and the clear value will be irrelevant. In most cases, of course, you can't know how far an element needs to be cleared. The way to make sure a cleared element has some space between its top and the bottom of a float is to put a bottom margin on the float itself. Therefore, if you want there to be at least 15 pixels of space below the float in the previous example, you would change the CSS like this: img.sider {float: left; margin: 0 0 15px;} h3 {border: 1px solid gray; clear: left;} The floated element's bottom margin increases the size of the float box, and thus the point past which cleared elements must be pushed. This is because, as you've seen before, the margin edges of a floated element define the edges of the floated box. |
< Day Day Up > |