CSS float and clear

float is one of the oldest layout tools in CSS. It was originally designed for a simple purpose: let an image sit to one side of a paragraph while the text wraps around it, just like a magazine layout. For years, developers stretched it far beyond that job to build entire multi-column page layouts, before Flexbox and Grid arrived and took over that role. Today float is used mostly for its original purpose — text wrapping around images or pull-quotes — but understanding it (and its partner property clear) is still essential, because floats show up in legacy code, in email HTML, and because the bugs they cause still trip up beginners.

Overview / How it works

Setting float: left or float: right on an element does two things at once. First, it takes the element out of the normal document flow. Normal flow is the default layout mode where block elements stack vertically and inline elements flow left-to-right, wrapping like text. A floated element is removed from that flow, meaning the elements after it no longer treat it as an obstacle in the vertical stacking sense — they behave as if the floated box’s height doesn’t exist for positioning purposes.

Second, the browser shifts the floated element as far as possible toward the left or right edge of its containing block, and then lets any inline-level content that follows (text, inline images, inline-block elements) wrap around it, hugging its other side. This is the key behavior that normal flow does not give you: a paragraph’s text will flow around a float sitting in the corner of that paragraph’s container, shortening its lines to make room.

Floating also changes the computed display of the element: a floated element always generates a block-level box (its outer display becomes block, or more precisely it participates in a block formatting context), even if you originally wrote display: inline. This is why a floated <span> can suddenly accept width and height.

The famous side effect of floats is that a parent element measures its own height by looking at the flow content inside it — and floated children are not part of flow. If a container holds nothing but floated children, the browser computes the container’s height as if it were empty, because there is no in-flow content to give it height. This is called collapsing, and it’s the single biggest source of float-related bugs. The clear property exists specifically to manage this: it tells an element “do not let yourself sit next to a float on this side — move down below it instead,” which is also the mechanism used to fix collapsing containers.

Syntax

selector {
  float: left | right | none | inline-start | inline-end;
  clear: left | right | both | none | inline-start | inline-end;
}
Value Applies to Meaning
float: left any element Pulls the box to the left edge of its container; later inline content wraps around its right side.
float: right any element Pulls the box to the right edge of its container; later inline content wraps around its left side.
float: none any element Default. The element stays in normal flow.
float: inline-start / inline-end any element Logical equivalents of left/right that respect the page’s writing direction (useful for right-to-left languages).
clear: left any element Element’s top edge moves below any earlier left-floated elements.
clear: right any element Element’s top edge moves below any earlier right-floated elements.
clear: both any element Element’s top edge moves below floats on both sides. The most commonly used value.

Note that clear only affects the element it is applied to — it pushes that one element down past floats that appear earlier in the document. It does not, by itself, fix a collapsed parent; for that you clear a pseudo-element or sibling positioned after the floats, inside the same parent (see Common Mistakes below).

Examples

Example 1: Wrapping text around a floated image

.article img {
  float: left;
  width: 160px;
  margin: 0 16px 8px 0;
  border-radius: 4px;
}

Applied to: <div class="article"><img src="cat.jpg" alt="A cat"><p>Long paragraph text...</p></div>

Result: The image sits in the top-left corner of the article block at 160px wide, with 16px of space on its right and 8px below it. The paragraph text that follows flows around the image’s right and bottom edges — the first several lines are shortened to make room for the image, and once the text passes below the image’s bottom edge, the lines return to full width.

This is the float’s original, still-legitimate use case: a magazine-style pull image with text wrapping, achieved with three lines of CSS and no Flexbox or Grid needed.

Example 2: The collapsing-parent problem and its fix

.card {
  border: 1px solid #ccc;
  padding: 12px;
}
.card .thumb {
  float: left;
  width: 80px;
  margin-right: 12px;
}
.card::after {
  content: "";
  display: block;
  clear: both;
}

Applied to: <div class="card"><img class="thumb" src="avatar.jpg" alt="Avatar"><p>Short caption text</p></div>

Result: The 1px border wraps snugly around both the floated thumbnail and the caption text, with 12px of padding on all sides showing correctly below the thumbnail. Without the .card::after rule, the border’s bottom edge would cut across the middle of the thumbnail image instead, because the card would measure itself as if the floated thumbnail contributed no height at all.

The ::after pseudo-element generates an invisible, empty block box as the last child of .card. Because it is a normal (non-floated) block, it must be placed in flow after the float — and because it’s told to clear: both, the browser pushes its top edge below the float. An empty block sitting below the float now exists inside .card, so .card has something in-flow to measure its height against, and it grows to enclose the float. This exact pattern is universally known as the “clearfix” and is still common in real codebases and CSS frameworks.

Example 3: A simple two-column layout using floats

.layout {
  width: 100%;
}
.layout::after {
  content: "";
  display: block;
  clear: both;
}
.sidebar {
  float: left;
  width: 25%;
  box-sizing: border-box;
  padding-right: 16px;
}
.main {
  float: left;
  width: 75%;
  box-sizing: border-box;
}

Result: The sidebar occupies the left 25% of the layout’s width and the main content occupies the right 75%, sitting side by side on the same horizontal row, because both are floated left and the widths sum to exactly 100%. The clearfix on .layout keeps the parent from collapsing to zero height.

This is the classic pre-Flexbox way to build a multi-column page. It still works today, but it’s brittle: if the widths ever add up to more than 100% (for example due to rounding, or extra margin), .main is pushed down onto its own row instead of sitting beside .sidebar. Modern code should prefer display: flex or display: grid for this kind of layout, which don’t have this fragility and don’t require a clearfix hack at all.

How it works step by step

  1. The browser lays out the containing block’s normal-flow content as usual, but when it reaches a floated element, it removes that element from the flow calculation.
  2. It computes the floated element’s own box (width, height, margins, padding, border) using the normal box model rules — floats still respect box-sizing, width, and margins exactly like block boxes do.
  3. The floated box is then positioned as far to the specified side (left or right) of its containing block as it can go, starting at the current “flow position” (i.e., it won’t float above content that came before it).
  4. If another float of the same side already occupies that horizontal space, the new float stacks next to it (not on top), continuing until it runs out of horizontal room, at which point it wraps to the next line down — this is how floated “gallery” layouts of same-sized boxes line up in a grid-like pattern.
  5. Any inline-level boxes (text runs, inline images) generated afterward in the same block formatting context are shortened on the side touching the float, creating the wrap effect. Other block-level boxes ignore the float horizontally and slide underneath it (their content still avoids overlapping it, but their border box can visually extend the full container width behind the float).
  6. The containing block computes its own auto height by looking only at in-flow content. Since floats are out of flow, they are skipped — unless the containing block itself establishes a new block formatting context (see below), in which case it explicitly includes floated descendants in its height calculation.
  7. When the browser reaches an element with clear set, it checks the bottom edge of the relevant floats that came before it and pushes that element’s top margin edge down until it is clear of them, before resuming normal placement.

One especially useful fact: giving a container overflow: hidden (or auto, or display: flow-root) makes it establish a new block formatting context, and an element that establishes a BFC always expands to contain its floated children. This is a shorter alternative to the clearfix pseudo-element, though overflow: hidden has the side effect of clipping anything that visually overflows the box, and display: flow-root (the modern, purpose-built fix) has no such side effect and no legacy-browser baggage on evergreen browsers.

Common Mistakes

Mistake 1: Forgetting to clear, and the parent collapses

.gallery {
  border: 2px solid #333;
}
.gallery .item {
  float: left;
  width: 100px;
  height: 100px;
  margin: 4px;
}

This looks reasonable, but because .gallery has no clearfix and no overflow/display: flow-root, it collapses to roughly zero height. Its visible border ends up drawn as a thin line running right through the middle of the floated items instead of enclosing them, and any background color on .gallery won’t show behind the items either. Fix it by adding a clearfix rule or switching the parent to a modern containment method:

.gallery {
  border: 2px solid #333;
  display: flow-root;
}
.gallery .item {
  float: left;
  width: 100px;
  height: 100px;
  margin: 4px;
}

display: flow-root creates a new block formatting context with no side effects, so .gallery now correctly wraps its floated .item children.

Mistake 2: Using float with a fixed pixel width that doesn’t account for box-sizing

.sidebar {
  float: left;
  width: 300px;
  padding: 20px;
  border: 1px solid #ddd;
}

Without box-sizing: border-box, the padding and border are added on top of the 300px content width, so the box actually renders about 342px wide. In a layout where a sibling float is sized to fill the remaining space, this extra width is enough to push that sibling onto a new line, breaking the intended side-by-side layout. Fix it by including box-sizing: border-box so the declared width includes padding and border:

.sidebar {
  float: left;
  width: 300px;
  padding: 20px;
  border: 1px solid #ddd;
  box-sizing: border-box;
}

Mistake 3: Trying to clear an element on the same line, thinking it clears itself

selector { clear: both; /* on the floated element itself */ }

A common misunderstanding is applying clear to the very element that is floated, expecting it to “clear itself” from other content. clear only matters for elements that are in normal flow and sit below earlier floats — it has no meaningful effect when applied to a floated element itself, since that element isn’t being placed relative to its own float. If you want a floated item’s later flow siblings to stop wrapping, apply clear to them, not to the float.

Best Practices

  • Reserve float for its original job — wrapping inline content (text) around an image or similar inset element — rather than full page layout.
  • Use Flexbox or Grid for multi-column layouts; they’re more predictable, don’t collapse their parent, and don’t need a clearfix.
  • Always pair a floated child with a way to contain it in its parent: display: flow-root on the parent is the cleanest modern choice.
  • Always set box-sizing: border-box on floated elements with padding or borders so declared widths behave predictably.
  • Give floated elements an explicit width — a float with no set width shrinks to fit its content, which is rarely what you want for layout purposes.
  • Add margin on the side of the float that faces the wrapping text, so text doesn’t touch the floated box’s edge.
  • Avoid floating more items across a row than reliably fit; rounding errors in percentage widths can silently wrap the last item to a new line.

Practice Exercises

  • Create a <div> containing a floated <img> (float left, 120px wide) followed by a paragraph of several sentences. Observe how the text wraps, then add clear: left to a new paragraph after it and observe how that second paragraph moves below the image instead of wrapping.
  • Build a three-item row of floated boxes, each 33.33% wide, inside a parent with a visible border. First observe the collapsed-parent bug, then fix it using a clearfix pseudo-element, and separately try fixing it again using only display: flow-root to compare the two approaches.
  • Take the two-column float layout from Example 3 and rebuild it using display: flex instead, keeping the same visual proportions. Compare how much CSS each approach needs.

Summary

  • float: left or float: right removes an element from normal flow and pushes it to one side of its container, letting inline content wrap around it.
  • A container with only floated children collapses to near-zero height unless it’s given a way to contain them — a clearfix pseudo-element, overflow: hidden/auto, or the modern display: flow-root.
  • clear: left | right | both pushes an in-flow element down below earlier floats on the specified side; it has no useful effect applied to the float itself.
  • Floats still respect the full box model, including box-sizing, so pair fixed widths with box-sizing: border-box when the element also has padding or a border.
  • Floats remain the right tool for wrapping text around an image; for full page and component layout, prefer Flexbox or Grid over float-based columns.