Floating Elements
Floating (adj. or verb) elements in CSS is a very common technique. The most common use for floating is to have text that flows around an image.
Floating used to also be utilized to achieve many different types of layouts in CSS. Luckily we have better techniques for that now, so in modern CSS, floats are only needed for this original intended purpose.
Here we'll break down exactly what happens when floating an element with some simple examples.
It only takes one declaration to float an element in CSS:
element {
float: left;
}
That's it, although you'll also need to make sure the parent element clears the floated content. More on that in a minute.
The float property accepts left
, right
, or none
. (There is no float: middle
.)
none
is the default, so you'd only need it when overriding a previously defined float setting on an element (such as in a media query).
What Floating Does
Here's what happens when you float an <element>
in CSS:
- Unlike normal block elements that grow as wide as their container,
<element>
shrinks to just the size of its contents. <element>
moves as high as possible within its container.- Elements that come after
<element>
move up and flow around it so long as there's enough room to the side. <element>
becomes block-level even if it normally would be an inline element.- However, unlike normal block elements,
<element>
does not share margins with anything around it. - Floated elements get partially removed from the document flow. This means that their container does not include them when determining how tall it needs to be. This is the only aspect of floats that's a little bit tricky.
The Fish Tank
When you float an element, think of its container as a fish tank.
The element, like an ice cube, floats up toward the top of the tank. It either floats all the way to the top, or it bumps into a sibling element that won't let it up any further.
Here's a plain old div in a fish tank:
HTML:<div class="fishtank"> <div>Div</div> </div>
CSS:/* backgrounds and borders omitted */ .fishtank { min-height: 300px; } .fishtank > div { margin: 5px; padding: 35px 20px; text-align: center; }
- Note that I gave the tank a
min-height
just to illustrate things, otherwise it would only be as tall as its contents (the div inside it). - I added some padding and margin on the div to make it bigger as well.
- Like normal, the div stretches as wide as its container.
Here's what happens when we float it:
HTML:<div class="fishtank"> <div class="floatme">Floating Div</div> </div>
CSS:/* floating div */ .floatme { float: left; }
- The div shrinks to the size of its contents (including its padding).
- It floats up until it bumps into something. In this case it was already at the top of its container.
- The margin on the floated div is what's keeping it slightly away from the very top left corner.
Now let's add some content, first without floating anything. I'll add some paragraphs:
HTML:<div class="fishtank"> <p>Lorem ipsum dolor sit...</p> <div>Div</div> <p>Nullam imperdiet...</p> <p>Curabitur convallis...</p> </div>
CSS:/* fishtank paragraphs */ .fishtank > p { margin: 10px 0; padding: 0 10px; }
- I gave the paragraphs some margins to separate them, and padding to keep the text away from the very edges.
- Both the div and the paragraphs have top and bottom margins of 10px, which they're sharing.
Don't take my word for it, you can confirm that the margins are being shared using your browser developer tools.
Ok now let's float that div again and see what happens:
HTML:<div class="fishtank"> <p>Lorem ipsum dolor sit...</p> <div class="floatme">Floating Div</div> <p>Nullam imperdiet...</p> <p>Curabitur convallis...</p> </div>
CSS:/* floating div */ .floatme { float: left; }
- The floating div moves up at high as it can until it bumps into another block element. Since the first paragraph is a normal block element, our floating div hits its ceiling there.
- Paragraphs that come after the div in our HTML move up under the floated element, and their content (the text) flows around it.
- Again, notice the tiny margin on the floating div, which keeps both the edge of the tank, and the paragraph text from touching it.
- Notice how the floating div no longer shares its margins with the margins of anything else.
Usage
So what is floating good for?
Flowing content
Mostly images, but potentially block quotes or any element that you want to have other content flow around. This is the main use that floating was designed for, like the example above.
Grid of Elements
Nope, we use CSS Grid for that now, although this method may still be used as a fallback for old browsers.
Using the code from the fish tank:
<div class="fishtank">
<div class="floatme">Floating Div</div>
<div class="floatme">Floating Div</div>
<div class="floatme">Floating Div</div>
<div class="floatme">Floating Div</div>
<div class="floatme">Floating Div</div>
<div class="floatme">Floating Div</div>
<div class="floatme">Floating Div</div>
<div class="floatme">Floating Div</div>
</div>
This is nice because it's pretty fluid; it will reflow when the browser window changes size. Play with the size of the browser window on this really big fish tank to see what I mean.
To keep the grid from reflowing, we'd simply set a width on the container. However, when determining the container width, you have to add up the floated elements' width, padding, borders, and margins. CSS Grid handles all that math for us!
Two (Multi) Column Layouts
Nope, we use CSS Grid for this too now! Floating elements to create multi-column layouts was the most common method until the recent (officially march 2017) support of CSS Grid.
This method may still be used as a fallback for older browsers.
The Tricky Bit: Clearfix
As mentioned in the very beginning, floating an element partially removes it from the flow of the document. A floated element's height is ignored when the container calculates how tall it needs to be.
Without backgrounds or borders on things, it's very common to have a floated element extend below the bottom of its container without being immediately obvious. This can cause lots of wacky problems with your layout!
Watch what happens if the fishtank doesn't have a min-height
:
<div class="fishtank">
<div class="floatme">Floating Div</div>
</div>
Not cool floating div! Now you're running into other elements on the page that are supposed to be separate!
There are a few ways to fix this, and you only need to choose one.
Option 1: Set an Overflow property
Setting overflow
on the parent element is an elegant solution. This is the best method because it doesn't require adding extra markup to your HTML.
HTML:<div class="fishtank"> <div class="floatme">Floating Div</div> </div>
CSS:.fishtank { overflow: auto; }
You can also use overflow: hidden
. You may have to choose which property to use in a given situation depending on potential side effects. For example, overflow: hidden
can affect box-shadow
and certain other properties.
Option 2: the Clear property
The CSS property clear
prevents an element from moving up and flowing around a floated element, which is very useful. The clear
property can be left
, right
, both
, or none
. The default is none
.
To apply this property as a clearfix, you can add a clearing element inside the container at the very bottom. This tricks the container into extending to include any floated elements, since it knows it has to include the clearing element afterward.
HTML:<div class="fishtank"> <div class="floatme">Floating Div</div> <div class="clear"></div> </div>
CSS:.clear { clear: both; }
Try adding border: 1px solid red;
to the clearing div using your browser developer tools. The clearing div has 0
height since it is empty, but you'll see that it still extends the full width of its container, like a normal block element.
The main drawback to this method is that it requires adding otherwise pointless extra markup to our HTML, just for styling.
Option 3: Add a Pseudo-Element
Finally, another way to tackle this problem is to trick the parent into clearing the floated elements by adding an empty pseudo-element through CSS. Like the overflow
method, this is much cleaner than adding extra markup to the HTML.
HTML:<div class="fishtank clearfix"> <div class="floatme">Floating Div</div> </div>
CSS:.clearfix::after { content: ""; display: table; clear: both; }
These seem like a bunch of hacks.
They are. This is admittedly not a very well covered problem in the CSS Float spec. A new property is currently under development that will properly solve this problem. It's called display: flow-root
. Caniuse link in the footer.