1044

Although elements like <div>s normally grow to fit their contents, using the float property can cause a startling problem for CSS newbies: If floated elements have non-floated parent elements, the parent will collapse.

For example:

<div>
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
</div>

The parent div in this example will not expand to contain its floated children - it will appear to have height: 0.

How do you solve this problem?

I would like to create an exhaustive list of solutions here. If you're aware of cross-browser compatibility issues, please point them out.

Solution 1

Float the parent.

<div style="float: left;">
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
</div>

Pros: Semantic code.
Cons: You may not always want the parent floated. Even if you do, do you float the parents' parent, and so on? Must you float every ancestor element?

Solution 2

Give the parent an explicit height.

<div style="height: 300px;">
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
</div>

Pros: Semantic code.
Cons: Not flexible - if the content changes or the browser is resized, the layout will break.

Solution 3

Append a "spacer" element inside the parent element, like this:

<div>
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
  <div class="spacer" style="clear: both;"></div>
</div>

Pros: Straightforward to code.
Cons: Not semantic; the spacer div exists only as a layout hack.

Solution 4

Set parent to overflow: auto.

<div style="overflow: auto;">
  <div style="float: left;">Div 1</div>
  <div style="float: left;">Div 2</div>
</div>

Pros: Doesn't require extra div.
Cons: Seems like a hack - that's not the overflow property's stated purpose.

Comments? Other suggestions?

Community
  • 1
  • 1
Nathan Long
  • 113,812
  • 91
  • 316
  • 418
  • 37
    I didn't know about the overflow:auto trick - I'd always used the clearing div approach. Thanks for the tip. – Herb Caudill Oct 20 '08 at 18:37
  • 7
    Tip: Solution 4 seems to work for Firefox 3+, but not IE7. For that you need solution 3 – Manos Dilaverakis Sep 03 '09 at 14:02
  • Thanks for the info, I went with 3, couldn't get the first solution to work, perhaps I had a parent parent without float, like you suggested :) – Doug Molineux Mar 15 '11 at 02:13
  • Positioning the parent is another option. e.g. giving it 'position:absolute' or 'position:fixed' – Jake Jul 29 '12 at 03:36
  • 9
    as seen here http://stackoverflow.com/questions/11830433/overflowauto-adding-scrollbars-in-chrome-ie `overflow:auto` seems to have some issues where it adds scrollbars where there shouldn't be any, so instead use `overflow:hidden` – Rodolfo Aug 06 '12 at 15:42
  • @Nathan Long, would you mind marking my answer as the correct one? It seems to have been accepted otherwise. – A.M.K Sep 16 '12 at 12:44
  • 2
    Regarding the `overflow` property, you may be interested in my answer to the following question: [Why does overflow: hidden have the unexpected side-effect of growing in height to contain floated elements?](http://stackoverflow.com/questions/12783064/why-does-overflow-hidden-have-the-unexpected-side-effect-of-growing-in-height-t) – BoltClock Oct 18 '12 at 16:14
  • 9
    +1 for the `overflow: auto`. That's the only one that worked for me. – Chris Redford Jul 23 '13 at 00:32
  • overflow: auto; was exactly what I was looking for at this moment in time, You have saved me time and for that you get +1 from me great solutions. It even works in IE 7+ – TURTLE Jul 29 '13 at 00:31
  • I don't get why browsers render parents with 0 height with child floats. I can understand if the child elements are positioned absolute or fixed, but the behaviour makes no sense in this scenario. – MacroMan Jan 28 '14 at 15:11
  • it'd be great if this oveflow auto worked for absolute position as well – Muhammad Umer Jun 08 '14 at 04:56
  • 1
    Since I asked this question, flexbox has come along. It looks like a great solution for many places where floats were formerly used: http://flexboxin5.com/ – Nathan Long Mar 11 '15 at 16:53
  • Check for missing opening/closing tags! This was driving me mad until I realised I had a closing div without the opener. That was the whole problem. – Lisandro Sep 20 '16 at 20:22
  • @Lisandro - you should use an IDE which detects those missing opening/closing tags for you. IntelliJ, visual studio, and many more will save you lots of time by finding these errors immediately during development. – TetraDev Sep 21 '16 at 19:40
  • any place i can look up why the overflow works on floated? – carinlynchin Nov 30 '16 at 18:53
  • 1
    solutions don't belong in questions! - should have edited the top rated solution – Julix Nov 08 '17 at 21:24
  • @Julix While I agree with you in principle, this is a question I asked and updated nine years ago. I had long ago made it a community wiki, leaving it to the community to maintain, and forgotten about it. It's since been closed as a duplicate. If you have strong opinions about it, please feel free to make edits. – Nathan Long Nov 09 '17 at 16:48
  • No strong opinions, sorry for the explanation mark - it overstated my position. "I thought solutions don't belong in questions. Now I'm confused... - Wouldn't the proper way to approach this be to edit the top rated solution?" - is a more accurate representation of my thoughts as I remember them now. - and I didn't even see this is now marked as duplicate. Wouldn't expect that on a 800+ vote item. – Julix Nov 13 '17 at 08:10
  • If you're having problems with scrollbars showing when using `overflow: auto` you can use `overflow: hidden` instead. Keep in mind anything extending outside of the element will be hidden, including CSS shadows. – Gavin Jan 07 '19 at 07:43
  • Can I ask why this behavior occurs ? whats the root cause ? – Usman I Aug 02 '19 at 11:39
  • the clear:both spacer (solution 3) works good – zdanman Oct 09 '20 at 12:56

15 Answers15

548

Solution 1:

The most reliable and unobtrusive method appears to be this:

Demo: http://jsfiddle.net/SO_AMK/wXaEH/

HTML:

<div class="clearfix">
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>
</div>​

CSS:

.clearfix::after { 
   content: " ";
   display: block; 
   height: 0; 
   clear: both;
}

​With a little CSS targeting, you don't even need to add a class to the parent DIV.

This solution is backward compatible with IE8 so you don't need to worry about older browsers failing.

Solution 2:

An adaptation of solution 1 has been suggested and is as follows:

Demo: http://jsfiddle.net/wXaEH/162/

HTML:

<div class="clearfix">
    <div style="float: left;">Div 1</div>
    <div style="float: left;">Div 2</div>
</div>​

CSS:

.clearfix::after { 
   content: " ";
   display: block; 
   height: 0; 
   clear: both;
   *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML += '<div class="ie7-clear"></div>' );
}

.ie7-clear {
    display: block;
    clear: both;
}

This solution appears to be backward compatible to IE5.5 but is untested.

Solution 3:

It's also possible to set display: inline-block; and width: 100%; to emulate a normal block element while not collapsing.

Demo: http://jsfiddle.net/SO_AMK/ae5ey/

CSS:

.clearfix {
    display: inline-block;
    width: 100%;
}

This solution should be backward compatible with IE5.5 but has only been tested in IE6.

Arsen Khachaturyan
  • 6,472
  • 4
  • 32
  • 36
A.M.K
  • 15,539
  • 3
  • 27
  • 61
  • 9
    -1 Inline block with 100% has undesired effects when you have padding on that element. -1 :after doesnt work in ie6 – lededje Oct 19 '12 at 10:07
  • 14
    @lededje: IE6 (hell, even IE7) has a broken float model which can never be completely remedied with any sort of clearfix. – BoltClock Oct 19 '12 at 10:38
  • 1
    @BoltClock Quite true, I also never actually tested these in actual versions of the browsers, I use(d) the Adobe BrowserLab. – A.M.K Oct 19 '12 at 12:03
  • 1
    @lededje You may have a valid point but i'm not supposed to do all the work for you. You can test these methods and if they don't work for you _find another solution_ or just change them, they're not that hard to understand. – A.M.K Oct 19 '12 at 12:04
  • 4
    like seriously who cares about IE6 :D IE8, i would understand that but IE6 is too much even for 2012 :P – Dany Khalife Jun 21 '13 at 03:56
  • These solutions just don't work for my page. – Chris Redford Jul 23 '13 at 00:31
  • @ChrisRedford If you are having any specific issues, please ask a question on the main Stack Overflow site. – A.M.K Jul 23 '13 at 14:13
  • Ah. Well, the `overflow: auto` solution in the OP worked for me, so I'm just using that. – Chris Redford Jul 23 '13 at 17:41
  • +1 inline-block (with overflow: hidden and padding) works a treat in my case: floating a couple of block elements inside a parent div. yeah, I'm actually developing something for IE6 over here right now. In 2013 o_O – Darragh Enright Nov 22 '13 at 09:19
  • What kind of user-targeting decision makes a project consider IE6 users? Nowadays the represent the 0.1% of Users (http://www.w3schools.com/browsers/browsers_explorer.asp) – Hector Ordonez Feb 03 '14 at 11:40
  • @MrMe, I personally never develop for IE6 (still have to do IE7 though), but you'd have to develop for it if you're making a website for a company that uses it. – A.M.K Feb 03 '14 at 21:24
  • Awesome, like all 3 solutions. – Ranjit Swain Apr 28 '14 at 09:48
  • 1
    I think the `content: " ";` can be `content: "";`, which would be more clean. – p3nchan Aug 25 '15 at 07:44
  • Solution 1 is awesome ! I'm really sick of the redundant and meaningless `
    `..
    – raven Jun 08 '16 at 03:49
  • -1 in pro of standards.... as this doesn't inlcudes the official W3 clearfix (http://www.w3schools.com/css/tryit.asp?filename=trycss_layout_clearfix), offered in another answer by Bobby. – DavidTaubmann Jun 21 '16 at 22:37
  • 6
    @davidtaubmann W3Schools is __not__ by any means official or part of the standards, they are operated by a third-party corporation that is not affiliated with the W3C. Although they've improved a lot over the past few years, many developers still know them as a bad source of information. I'd suggest you look at the MDN or Web Platform Docs (far less comprehensive, but official) in general for docs. I omitted the `overflow: auto` trick because it's mentioned in the question that asks for other suggestions. – A.M.K Jun 22 '16 at 12:35
  • that really is awesome...but does anyone know WHY it works? (the overflow: auto) – carinlynchin Jul 12 '16 at 19:50
  • @carine, I don't have any official source to back this up, but as far as I understand, it works like this: An element in its default state lets any content inside of it overflow (`overflow: visible`), so it really doesn't need to know how tall it is to display properly. Once you set overflow: auto/scroll it needs to calculate its own height to see if it's max-height or maximum available space has been passed. Once that's calculated, it's used in layout and the element no longer collapses, because it now matters how tall it is. I hope that makes sense. – A.M.K Jul 13 '16 at 01:24
  • @Carine It should be the same idea with `display: inline-block` (which is my only original solution). If an element is inline things wrap around it, so its dimensions in both directions need to be calculated. Setting its width to 100% doesn't affect the layout process so that works as well. AFAICT, the core idea behind a clearfix is to make the parent element's height important to the browser so the calculations are made and the results acted on. – A.M.K Jul 13 '16 at 01:28
79

I usually use the overflow: auto trick; although that's not, strictly speaking, the intended use for overflow, it is kinda related - enough to make it easy to remember, certainly. The meaning of float: left itself has been extended for various uses more significantly than overflow is in this example, IMO.

Josh Crozier
  • 202,159
  • 50
  • 343
  • 273
Bobby Jack
  • 14,812
  • 10
  • 59
  • 94
  • Congratulations, this is exactly the official w3 solution: http://www.w3schools.com/css/tryit.asp?filename=trycss_layout_clearfix – DavidTaubmann Jun 21 '16 at 22:34
  • 21
    W3 != W3Schools, actually W3Schools imho hosts very "fishy" content in regards to standard HTML. – D.R. Sep 18 '16 at 17:30
  • 2
    Regarding W3Schools, I think they've gotten at least a little better over the years, but is it important to realize that, like @D.R. said, They are not The World Wide Web Consortium (W3C) – TecBrat Jul 05 '19 at 14:29
20

Rather than putting overflow:auto on the parent, put overflow:hidden

The first CSS I write for any webpage is always:

div {
  overflow:hidden;
}

Then I never have to worry about it.

Josh Crozier
  • 202,159
  • 50
  • 343
  • 273
tybro0103
  • 43,805
  • 32
  • 138
  • 167
  • 11
    This is a bad idea. You don't want to clip anything randomly especially if you set fixed dimensions on those divs. Furthermore, there are cases where `overflow: auto` is preferred over `overflow: hidden` (e.g. you want content to be scrollable when it overflows). – BoltClock Oct 18 '12 at 16:17
  • 1
    Since I posted this, I have stopped using that as a global default. I do think that `overflow:hidden` is most often the best solution. Every case is different. Thanks for pointing that out ;) – tybro0103 Oct 19 '12 at 18:31
  • No problem - I thought I'd add the comment anyway for posterity, in case it ever comes up again. – BoltClock Oct 19 '12 at 18:34
  • Side-Effect: http://stackoverflow.com/questions/12783064/why-does-overflow-hidden-have-the-unexpected-side-effect-of-growing-in-height-t?lq=1 – Griffin Apr 24 '13 at 05:39
18

The problem happens when a floated element is within a container box, that element does not automatically force the container’s height adjust to the floated element. When an element is floated, its parent no longer contains it because the float is removed from the flow. You can use 2 methods to fix it:

  • { clear: both; }
  • clearfix

Once you understand what is happening, use the method below to “clearfix” it.

.clearfix:after {
    content: ".";
    display: block;
    clear: both;
    visibility: hidden;
    line-height: 0;
    height: 0;
}

.clearfix {
    display: inline-block;
}

html[xmlns] .clearfix {
    display: block;
}

* html .clearfix {
    height: 1%;
}

Demonstration :)

Jesse
  • 8,035
  • 7
  • 42
  • 56
Sarfraz
  • 355,543
  • 70
  • 511
  • 562
  • I have a problem with floats collapsing my div border on ie6. I added `height: 0` which fixed ie6 but broke ie7 and up. :( Turns out `height: 1%` fixes ie6 and doesn't destroy ie7up! :D – bloodyKnuckles Dec 19 '16 at 22:44
15

There are several versions of the clearfix, with Nicolas Gallagher and Thierry Koblentz as key authors.

If you want support for older browsers, it's best to use this clearfix :

.clearfix:before, .clearfix:after {
    content: "";
    display: table;
}

.clearfix:after {
    clear: both;
}

.clearfix {
    *zoom: 1;
}

In SCSS, you should use the following technique :

%clearfix {
  &:before, &:after {
    content:" ";
    display:table;
  }

  &:after {
    clear:both;
  }

  & {
    *zoom:1;
  }
}

#clearfixedelement {
    @extend %clearfix;
}

If you don't care about support for older browsers, there's a shorter version :

.clearfix:after {
    content:"";
    display:table;
    clear:both;
}
John Slegers
  • 38,420
  • 17
  • 182
  • 152
9

Strange no one has come up with a complete answer for this yet, ah well here it is.

Solution one: clear: both

Adding a block element with the style clear:both; onto it will clear the floats past that point and stop the parent of that element from collapsing. http://jsfiddle.net/TVD2X/1/

Pros: Allows you to clear an element and elements you add below will not be effected by the floated elements above and valid css.

Cons: Requires the another tag to clear the floats, bloating markup.

Note: To fall back to IE6 and for it to work on abstinent parents (i.e. the input element) you are not able to use :after.

Solution two: display: table

Adding display:table; to the parent to make it shrug off the floats and display with the correct height. http://jsfiddle.net/h9GAZ/1/

Pros: No extra markup and is a lot neater. Works in IE6+

Cons: Requires invalid css to make sure everything plays nice in IE6 and 7.

Note: The IE6 and 7 width auto is used to prevent the width being 100%+padding, which is not the case in newer browsers.

A note on the other "solutions"

These fixes work back to the lowest supported browser, over 1% usage globally (IE6), which means using :after does not cut it.

Overflow hidden does show the content but does not prevent the element from collapsing and so does not answer the question. Using an inline block can have buggy results, children having strange margins and so on, table is much better.

Setting the height does "prevent" the collapse but it is not a proper fix.

Invalid css

Invalid css never hurt anyone, in fact, it is now the norm. Using browser prefixes is just as invalid as using browser specific hacks and doesn't impact the end user what so ever.

In conclusion

I use both of the above solutions to make elements react correctly and play nicely with each other, I implore you to do the same.

Community
  • 1
  • 1
lededje
  • 1,789
  • 1
  • 14
  • 25
  • 1
    Since when did IE6 support `display: table`? – BoltClock Oct 19 '12 at 10:44
  • [rant] See http://caniuse.com/#feat=css-table, for a full compatibility list. IE 6 and 7 have _no_ support for `display: table;`. As for your other solution, it's already mentioned in the question which asks for "_Other_ suggestions". Please read the question and all answers before providing your own answer and downvoting others. Another point, invalid CSS may not "hurt" anyone but it's invalid CSS regardless, and vendor prefixes aren't just an accepted norm, look in the Chrome inspector and you'll see that it doesn't just consider them invalid, _they aren't processed at all_. [/rant] – A.M.K Oct 19 '12 at 11:58
  • [response to rant]First of all, the above methods are tested back to IE6 and they *all* work just fine. Supply a non-working example and get back to me. Vendor specific rules are not meant to be processed in browsers that they don't apply to (that's what vendor specific means...) So yes, of course they are not going to be processed... that's the point, but it still allows you to use bleeding edge css rules.[/response to rant] – lededje Oct 19 '12 at 12:52
  • That your `display: table` method works in IE6/IE7 has nothing to do with `display: table` and everything to do with `zoom: 1`. See http://jsfiddle.net/BoltClock/h9GAZ/2 (removed `zoom: 1`) and http://jsfiddle.net/BoltClock/h9GAZ/3 (removed `display: table`). Coupled with the statement "Requires invalid css [for] IE6 and 7", that is akin to saying that method doesn't work in those versions at all. – BoltClock Oct 19 '12 at 13:37
  • Zoom:1; is not valid css any more? – lededje Oct 19 '12 at 15:55
  • 1
    `zoom` was never in any CSS specification... it was created and used by Microsoft alone. – BoltClock Oct 19 '12 at 16:03
  • Making it invalid CSS...? I don't know where you are going with this; it is not useful nor is it going to amount to anything. The above answer works, end of. – lededje Oct 19 '12 at 17:55
  • My point is that you're saying `display: table` works in IE6+, which is completely untrue. The `zoom: 1` patch is there for its own sake and has nothing to do with `display: table`, so saying the `display: table` solution works in IE6 is misleading at best. I didn't say using invalid CSS is wrong - I don't really care about that either, but on the other hand I do care about misleading answers. – BoltClock Oct 19 '12 at 18:36
  • I was just distinguishing one from t'other, no need to (as you so professionally put it) [rant] about it. The fiddles are there to give working versions on what I meant in each solution. Please just drop it. OAO – lededje Oct 19 '12 at 19:33
  • The `display: table` solution was actually the only one that worked in my context (Chrome extension injecting CSS in a complex site). Huge thanks for that! – cprcrack Oct 11 '13 at 19:56
  • -1 for stating this is a complete answer – andygoestohollywood Oct 18 '13 at 08:44
9

Although the code isn't perfectly semantic, I think it's more straightforward to have what I call a "clearing div" at the bottom of every container with floats in it. In fact, I've included the following style rule in my reset block for every project:

.clear 
{
   clear: both;
}

If you're styling for IE6 (god help you), you might want to give this rule a 0px line-height and height as well.

Bryan A
  • 3,504
  • 1
  • 20
  • 29
  • if you've got something like a Facebook 'Like' box inside your element you'll need to use this method or else when you click 'Like' the Facebook comment box will be cropped. – Simon_Weaver Jul 03 '13 at 11:01
9

The ideal solution would be to use inline-block for the columns instead of floating. I think the browser support is pretty good if you follow (a) apply inline-block only to elements that are normally inline (eg span); and (b) add -moz-inline-box for Firefox.

Check your page in FF2 as well because I had a ton of problems when nesting certain elements (surprisingly, this is the one case where IE performs much better than FF).

DisgruntledGoat
  • 62,693
  • 62
  • 192
  • 281
6

I use 2 and 4 where applicable (i.e. when I know the content's height or if overflowing doesn't harm). Anywhere else, I go with solution 3. By the way, your first solution has no advantage over 3 (that I can spot) because it isn't any more semantic since it uses the same dummy element.

By the way, I wouldn't be concerned about the fourth solution being a hack. Hacks in CSS would only be harmful if their underlying behaviour is subject to reinterpretation or other change. This way, your hack wouldn't be guaranteed to work. However in this case, your hack relies on the exact behaviour that overflow: auto is meant to have. No harm in hitching a free ride.

Konrad Rudolph
  • 482,603
  • 120
  • 884
  • 1,141
5

My favourite method is using a clearfix class for parent element

.clearfix:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}

.clearfix {
    display: inline-block;
}

* html .clearfix {
    height: 1%;
}

.clearfix {
    display: block;
}
Josh Crozier
  • 202,159
  • 50
  • 343
  • 273
4

One of the most well known solutions is a variation of your solution number 3 that uses a pseudo element instead of a non-semantic html element.

It goes something like this...

.cf:after {
    content: " ";
    display: block;
    visibility: hidden;
    height: 0;
    clear: both;
}

You place that in your stylesheet, and all you need is to add the class 'cf' to the element containing the floats.

What I use is another variation which comes from Nicolas Gallagher.

It does the same thing, but it's shorter, looks neater, and maybe used to accomplish another thing that's pretty useful - preventing the child elements' margins from collapsing with it's parents' (but for that you do need something else - read more about it here http://nicolasgallagher.com/micro-clearfix-hack/ ).

.cf:after {
    content: " ";
    display: table;
    clear: float;
}
João Paulo Macedo
  • 14,267
  • 4
  • 29
  • 39
3

add this in the parent div at the bottom

 <div style="clear:both"></div>
2

The main problem you may find with changing overflow to auto or hidden is that everything can become scrollable with the middle mouse buttom and a user can mess up the entire site layout.

will-hart
  • 3,428
  • 1
  • 35
  • 46
2

Another possible solution which I think is more semantically correct is to change the floated inner elements to be 'display: inline'. This example and what I was working on when I came across this page both use floated divs in much exactly the same way that a span would be used. Instead of using divs, switch to span, or if you are using another element which is by default 'display: block' instead of 'display: inline' then change it to be 'display: inline'. I believe this is the 100% semantically correct solution.

Solution 1, floating the parent, is essentially to change the entire document to be floated.

Solution 2, setting an explicit height, is like drawing a box and saying I want to put a picture here, i.e. use this if you are doing an img tag.

Solution 3, adding a spacer to clear float, is like adding an extra line below your content and will mess with surrounding elements too. If you use this approach you probably want to set the div to be height: 0px.

Solution 4, overflow: auto, is acknowledging that you don't know how to lay out the document and you are admitting that you don't know what to do.

Jonathan
  • 63
  • 1
  • 3
  • Do you mean to remove the float declaration as well? Because floated elements cannot be anything *but* display: block. – BoltClock Mar 29 '13 at 16:18
0

I believe that best way is to set clear:both to the upcoming element.

Here's why:

1) :after selector is not supported in IE6/7 and buggy in FF3, however,
     if you care only about IE8+ and FF3.5+ clearing with :after is probably best for you...

2) overflow is supposed to do something else so this hack isn't reliable enough.

Note to author: there is nothing hacky on clearing... Clearing means to skip the floating fields. CLEAR is with us since HTML3 (who knows, maybe even longer) http://www.w3.org/MarkUp/html3/deflists.html , maybe they should chose a bit different name like page: new, but thats just a detail...

Josh Crozier
  • 202,159
  • 50
  • 343
  • 273
jave.web
  • 11,102
  • 9
  • 70
  • 98