clear property & float issues
The clear property prevents an element from flowing next to floated elements. clear: left clears floated-left elements, clear: right clears floated-right, and clear: both clears both directions. The main challenges with floats are float collapse (parent height becomes zero) and unwanted text wrapping. Modern solutions include the overflow property, flexbox, and grid.
The clear property
Value | Clears floats | Behavior |
|---|---|---|
| None (default) | Element flows normally next to floats |
| Left floats | Element moves below left-floated elements |
| Right floats | Element moves below right-floated elements |
| Both directions | Element moves below all floated elements |
| Start direction | Clear in document direction start |
| End direction | Clear in document direction end |
<!-- Two floated elements, then content -->
<div class="float-left">Left float</div>
<div class="float-right">Right float</div>
<p class="content">Content text</p>
.float-left {
float: left;
width: 200px;
}
.float-right {
float: right;
width: 200px;
}
.content {
/* Without clear, text flows next to floats */
[Left] Content text flows here [Right]
}
.content {
clear: both;
/* With clear: both, content moves below floats */
[Left] [Right]
Content text below floats
}Float collapse and containment
Float collapse occurs when a parent contains only floated children — the parent height becomes zero because floats don't contribute to height. Several solutions exist.
<!-- Float collapse problem -->
<div class="container">
<div class="column float-left">Column 1</div>
<div class="column float-left">Column 2</div>
<!-- both children are floated -->
</div>
.container {
background: blue;
/* Height is 0 because children are floated */
/* Container appears as thin blue line */
}
.column {
float: left;
width: 50%;
height: 200px;
/* doesn't affect parent height */
}
<!-- Solutions -->
<!-- Solution 1: Overflow (cleanest for simple cases) -->
.container {
overflow: auto; /* or overflow: hidden */
/* Establishes block formatting context */
/* Contains floats, height is calculated */
}
<!-- Solution 2: Clearfix (legacy, still used) -->
.container::after {
content: '';
display: table;
clear: both;
}
<!-- Solution 3: Flexbox (modern, recommended) -->
.container {
display: flex;
/* Children don't need to float */
}
.column {
float: none; /* not needed with flexbox */
flex: 1; /* equal width */
}The overflow solution
Using overflow: auto or overflow: hidden on a parent creates a new block formatting context, which contains floated children and fixes collapse.
<!-- Overflow solution -->
<div class="container">
<div class="float-left">Floated</div>
<div class="float-left">Floated</div>
</div>
.container {
overflow: auto; /* contains floats */
/* No empty space needed for children */
}
.float-left {
float: left;
width: 50%;
}
<!-- Result: container height is calculated correctly -->
<!-- Caveats -->
.overflow-hidden {
overflow: hidden;
/* Works but clips any content that exceeds bounds */
}
.overflow-auto {
overflow: auto;
/* Works, adds scrollbar if content overflows (usually invisible) */
}
.overflow-scroll {
overflow: scroll;
/* Works but always shows scrollbar (awkward) */
}The clearfix hack
The clearfix is a CSS trick that uses a pseudo-element to clear floats. It's mostly legacy now but still appears in older codebases.
<!-- Clearfix hack -->
.container::after {
content: '';
display: table;
clear: both;
}
<!-- How it works -->
<!-- ::after pseudo-element is added to end of container -->
<!-- display: table makes it generate a box -->
<!-- clear: both positions it below all floats -->
<!-- Container height now includes the cleared pseudo-element -->
<!-- Alternative syntax (older version) -->
.container {
overflow: auto;
zoom: 1; /* IE6 hack */
}
.container::after {
content: '';
display: block;
height: 0;
visibility: hidden;
clear: both;
}
<!-- Modern recommendation: don't use clearfix -->
<!-- Use overflow: auto or flexbox instead -->Preventing unwanted text wrapping around floats
When you want an element to stay to the side of a float but prevent text wrapping, use the overflow property.
<!-- Text wrapping around float (not wanted) -->
<img class="float-left" src="image.jpg">
<div class="text-box">
Text flows around the image...
</div>
.float-left {
float: left;
width: 150px;
margin-right: 20px;
}
.text-box {
/* Text wraps around float */
This box fits next to the float and wraps
}
<!-- Solution: overflow on text box -->
.text-box {
overflow: auto; /* or overflow: hidden */
/* Creates block formatting context */
/* Box no longer wraps around float */
}
Result:
[Image] [Box with text that doesn't wrap]
[around the image ]
<!-- Alternative: flex container -->
<div class="container">
<img class="image" src="image.jpg">
<div class="text-box">Text here</div>
</div>
.container {
display: flex;
gap: 20px;
}
.image {
flex-shrink: 0; /* don't shrink image */
width: 150px;
}
.text-box {
flex: 1; /* take remaining space */
}Modern alternatives to floats
<!-- Legacy: float-based columns -->
.column {
float: left;
width: 33.333%;
padding: 10px;
}
<!-- Modern: flexbox -->
.container {
display: flex;
gap: 10px;
}
.column {
flex: 1; /* equal width */
padding: 10px;
}
<!-- Modern: grid -->
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.column {
padding: 10px;
}
<!-- Legacy: text wrapping with float -->
<img class="float-left" src="image.jpg">
<p>Text flows around image...</p>
<!-- Modern: flexbox with text -->
<div class="container">
<img src="image.jpg" alt="Image">
<p>Text next to image</p>
</div>
.container {
display: flex;
gap: 15px;
align-items: flex-start;
}Quick reference: clearing floats
<!-- Prevent element from flowing next to float -->
element {
clear: both; /* works, but element moves down */
}
<!-- Fix float collapse in parent -->
.parent {
overflow: auto; /* or overflow: hidden */
}
/* OR */
.parent::after {
content: '';
display: table;
clear: both;
}
/* OR (best modern solution) */
.parent {
display: flex; /* children don't need to float */
}
<!-- Prevent text wrapping around float -->
.text-box {
overflow: auto; /* or overflow: hidden */
}
/* OR */
.text-box {
display: flex; /* flex item doesn't wrap around floats */
}