AGS Logo AGS Logo

Fixing Misbehaving Floats
Using Flow Root

Even though we have many more options than we used to for layouts, there are still things that CSS float has no replacements for, like wrapping text around an image. One thing that hasn’t changed however, is the need to make float behave. More often than not, it’s the same old scenario: We have a background or border around our container and the floated element is sticking out.

Cards with text and images. The images are floated, in the second card, there is not enough text to completely wrap the image therefore, the image extends beyond the card and overlaps some of the next card as well

Typical Float Problem: the content exceeds the size of the container

What we ultimately want is for the image to be contained inside of the card. To achieve this, we have historically used all sorts of hacks to achieve this.

clear="both"

One option was to add a tag, often a line break (<br>) to which we would add a clear=“both” in order to clear the float and extend the container. The downside to this technique is that the added tags have no other purpose than to handle layout and styling intricacies. Maintainability was not ideal either, because if we chose to no longer float for example, we had to go find all these extra tags and remove them one by one. Listing 1 shows the clear=“both” trick applied to our html.

clear="both"
<div class="card">
  <h2>Off The Letter I</h2>
  <img src="i.png" alt="">
  <p>The letter I you are to make of a single broad vertical tract in the ...</p>
  <br clear=“both”>
</div>

<div class="card clearfix">
  <h2>Off The Letter K</h2> 
  <img src="k.png" alt="">
  <p>Now for K: You are to make the first tract vertical, in the same ...</p>
  <br clear=“both”>
</div>

Clearfix

Another very popular option was clearfix (Listing 2) which unlike clear="both" had the advantage of not requiring adding unnecessary tags to the markup.

Clearfix
.clearfix:after {
  visibility: hidden;
  display: block;
  font-size: 0;
  content: " ";
  clear: both;
  height: 0;
}
.clearfix { display: inline-block; }
/* start commented backslash hack \*/
* html .clearfix { height: 1%; }
.clearfix { display: block; }
/* close commented backslash hack */

This technique was later streamlined and renamed to group (Listing 3).

Group
.group:before,
.group:after {
  content: "";
  display: table;
} 
.group:after {
  clear: both;
}

Applied to our HTML (Listing 4), we add the clearfix class, or if using group then the group class to our card and the image now fits inside of its container.

Clearfix applied to HTML
<div class="card clearfix">
  <h2>Off The Letter I</h2>
  <img src="i.png" alt="">
  <p>The letter I you are to make of a single broad vertical tract in the ...</p>
</div>

<div class="card clearfix">
  <h2>Off The Letter K</h2> 
  <img src="k.png" alt="">
  <p>Now for K: You are to make the first tract vertical, in the same ...</p>
</div>

Both of the above techniques achieve the desired results but they are still workarounds. We now have a property value to do achieve the same results, which for the first time, is not a hack. We can now use display: flow-root.

display: flow-root

The CSS specification defines the flow root behavior as follows:

The element generates a block container box, and lays out its contents using flow layout. It always establishes a new block formatting context for its contents.

By setting our card's display property to flow-root, the card content will follow the normal flow layout, therefore our image will be floated as directed, but because the content has it's own block formatting context, the container will take the size of the card content including the floated image that would have extended passed it. In short it achieves the same results as the above 2 tricks but without the hacks. Our CSS (Listing 6) therefore look as follows:

Flow-Root applied to CSS
.card {
  display: flow-root;
}

We don't need any special classes or extras, we can simply add flow-root as a value to the display property for our card and get the desired result (Figure 2).

Cards with text and images. The images are floated, the container of the second card, which previously did not encompass the image, now extends past the image.

Fixed Container

So without any hacks or special knowledge, dutifully passed on from one generation of developers to another, we have a documented, consistent, baked-in solution. A full copy of the code presented in the article can be found below.

Happy Coding!

License: CC BY-NC-ND 4.0 (Creative Commons)