DekGenius.com
Previous Section  < Day Day Up >  Next Section

10.1 Floating

You 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:

The additions to your ALIGN options need a lot of explanation. First, the values "left" and "right". Images with those alignments are an entirely new floating image type.

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.

float


Values

left | right | none | inherit


Initial value

none


Applies to

all elements


Inherited

no


Computed value

as specified


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

However, when floating elements in CSS, some interesting issues come up.

10.1.1 Floated Elements

Keep 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 paragraph
figs/css2_1002.gif

One 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 margins
figs/css2_1003.gif

To 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 width
figs/css2_1004.gif
10.1.1.1 No floating at all

There 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 Details

Before 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>

We'll return to the concept of containing blocks when we discuss positioning later in this chapter.


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:

  1. The left (or right) outer edge of a floated element may not be to the left (or right) of the inner edge of its containing block.

    This is straightforward enough. The outer left edge of a left-floated element can only go as far left as the inner left edge of its containing block; similarly, the furthest right a right-floated element may go is its containg block's inner right edge, as shown in Figure 10-5. (In this and subsequent figures, the circled numbers show the position where the markup element actually appears in relation to the source, and the numbered boxes show the position and size of the floated visible element.)

Figure 10-5. Floating to the left (or right)
figs/css2_1005.gif
  1. The left (or right) outer edge of a floated element must be to the right (or left) of the right (left) outer edge of a left-floating (or right-floating) element that occurs earlier in the document's source, unless the top of the later element is below the bottom of the former.

    This rule prevents floated elements from "overwriting" each other. If an element is floated to the left, and another floated element is already there, the latter element will be placed against the outer right edge of the previously floated element. If, however, a floated element's top is below the bottom of all earlier floated images, then it can float all the way to the inner left edge of the parent. Some examples of this are shown in Figure 10-6.

    The advantage of this rule is that all your floated content will be visible since you don't have to worry about one floated element obscuring another. This makes floating a fairly safe thing to do. The situation is markedly different when using positioning, where it is very easy to cause elements to overwrite one another.

Figure 10-6. Keeping floats from overlapping
figs/css2_1006.gif
  1. The right outer edge of a left-floating element may not be to the right of the left outer edge of any right-floating element to its right. The left outer edge of a right-floating element may not be to the left of the right outer edge of any left-floating element to its left.

    This rule prevents floated elements from overlapping each other. Let's say you have a body that is 500-pixels wide, and its sole content is two images that are 300-pixels wide. The first is floated to the right, and the second is floated to the left. This rule prevents the second image from overlapping the first by 100-pixels. Instead, it is forced down until its top is below the bottom of the right-floating image, as depicted in Figure 10-7.

Figure 10-7. More overlap prevention
figs/css2_1007.gif
  1. A floating element's top may not be higher than the inner top of its parent. If a floating element is between two collapsing margins, then the floated element is placed as though it had a block-level parent element between the two elements.

    The first part of this rule is quite simple and keeps floating elements from floating all the way to the top of the document. The correct behavior is illustrated in Figure 10-8. The second part of this rule fine-tunes the alignment in situations—for example, when the middle of three paragraphs is floated. In that case, the floated paragraph is floated as if it had a block-level parent element (say, a div). This prevents the floated paragraph from moving up to the top of whatever common parent the three paragraphs share.

Figure 10-8. Unlike balloons, floated elements can't float upward
figs/css2_1008.gif
  1. A floating element's top may not be higher than the top of any earlier floating or block-level element.

    Similar to Rule 4, Rule 5 keeps floated elements from floating all the way to the top of their parent elements. It is also impossible for a floated element's top to be any higher than the top of a floated element that occurs earlier. Figure 10-9 is an example of this; here, you can see that since the second float was forced to be below the first one, the third float's top is even with the top of the second float, not the first.

Figure 10-9. Keeping floats below their predecessors
figs/css2_1009.gif
  1. A floating element's top may not be higher than the top of any line box that contains a box generated by an element that comes earlier in the document source.

    Similar to Rules 4 and 5, this rule further limits the upward floating of an element by preventing it from being above the top of a line containing content that precedes the floated element. Let's say that, right in the middle of a paragraph, there is a floated image. The highest the top of that image may be placed is the top of the line box from which the image originates. As you can see in Figure 10-10, this keeps images from floating too far upward.

Figure 10-10. Keeping floats level with their context
figs/css2_1010.gif
  1. A left (or right) floating element that has another floating element to its left (right) may not have its right outer edge to the right (left) of its containing block's right (left) edge.

    In other words, a floating element cannot stick out beyond the edge of its containing element, unless it's too wide to fit on its own. This prevents a situation where a succeeding number of floated elements could appear in a horizontal line and far exceed the edges of the containing block. Instead, a float that would otherwise stick out of its containing block by appearing next to another one will be floated down to a point below any previous floats, as illustrated by Figure 10-11 (in the figure, the floats start on the next line in order to more clearly illustrate the principle at work here). This rule first appeared in CSS2, to correct its omission in CSS1.

Figure 10-11. If there isn't room, floats get pushed to a new "line"
figs/css2_1011.gif
  1. A floating element must be placed as high as possible.

    Rule 8 is, of course, subject to the restrictions introduced by the previous seven rules. Historically, browsers aligned the top of a floated element with the top of the line box after the one in which the image's tag appears. Rule 8, however, implies that its top should be even with the top of the same line box as that in which its tag appears, assuming there is enough room. The theoretically correct behaviors are shown in Figure 10-12.

Figure 10-12. Given the other constraints, go as high as possible
figs/css2_1012.gif

Unfortunately, since there is no precisely defined meaning for "as high as possible" (which could mean, and in fact has been argued to mean, "as high as conveniently possible"), you cannot rely on consistent behavior even among browsers that are considered CSS1-conformant. Some browsers will follow historical practice and float the image down into the next line, while others will float the image into the current line if there is room to do so.


  1. A left-floating element must be put as far to the left as possible, and a right-floating element as far to the right as possible. A higher position is preferred to one that is further to the right or left.

    Again, this rule is subject to restrictions introduced in the preceding rules. There are similar caveats here as in Rule 8, although they are not quite so fuzzy. As you can see from Figure 10-13, it is pretty easy to tell when an element has gone as far as possible to the right or left.

Figure 10-13. Get as far to the left (or right) as possible
figs/css2_1013.gif

10.1.3 Applied Behavior

There 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 behavior
figs/css2_1014.gif

Nothing 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 elements
figs/css2_1015.gif

There 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.

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


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

Because 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 margins

Interestingly, 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 margins
figs/css2_1017.gif

Contrary 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 margins
figs/css2_1018.gif

The 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 parent
figs/css2_1019.gif

10.1.4 Floats, Content, and Overlapping

An 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:

  • An inline box that overlaps with a float has its borders, background, and content all rendered "on top" of the float.

  • A block box that overlaps with a float has its borders and background rendered "behind" the float, whereas its content is rendered "on top" of the float.

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

The 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.

The described overlapping behavior is independent of the document source order. It does not matter if an element comes before or after a float: the same behaviors still apply.


10.1.5 Clearing

We'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 clear
figs/css2_1021.gif

This is done with clear.

clear


Values

left | right | both | none


Initial value

none


Applies to

block-level elements


Inherited

no


Computed value

as specified


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

In 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 sides
figs/css2_1023.gif

If, 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 all
figs/css2_1024.gif

In 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 margins
figs/css2_1025.gif

There 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.

    Previous Section  < Day Day Up >  Next Section