5

Below is a menu inside a header. The ul and li elements are floating and are now floating underneath the header, which I've tried to prevent with clear:both. However, that doesn't seem to work so I wonder... what can be wrong?

html:

<header>
    <ul>
        <li><a href='#'>Item 1</a></li>
        <li><a href='#'>Item 2</a></li>
        <li><a href='#'>Item 3</a></li>
        <li><a href='#'>Item 4</a></li>
    </ul>
    <div class='clear'/>
</header>

css:

header {
    background: #888;
    height: 20px;
    padding: 10px;
}

ul{
  margin: 18px 0;
  padding: 0;
  list-style: none;
}

ul li{
  margin: 0 10px 0 0;
  padding: 0;
  display: block;
  float: left;
  width: 80px;
  height: 20px;
  border: 1px solid #000;
  background: red;
}

ul li a{
  display:block;
  width: 100%;
  height: 100%;
  text-decoration: none;
  float: left;
  text-align: center;
  padding-top: 2px;
}

ul li a:hover{
  color: #fff;
  background-color: #000;
}​

.clear {
    clear:both;
}
braX
  • 11,506
  • 5
  • 20
  • 33
holyredbeard
  • 19,619
  • 32
  • 105
  • 171
  • What are you trying to accomplish here? That div is empty, so what's the point of having it in the header? – random_user_name Oct 20 '12 at 14:16
  • The problem is that the `li`s are floated too. – Gareth Oct 20 '12 at 14:16
  • 2
    Not an answer, but I always feel better about using the `overflow: hidden` hack on the container. – PeeHaa Oct 20 '12 at 14:18
  • 1
    You might want to abondon the `float` concept here. There's a great way to get `display: inline-block` to work (even in old IE browsers) and achieve what you want with better, simpler code. And @PeeHaa is right - if you are going to float, `overflow: hidden` is a better hack for forcing the container to wrap the floats. – random_user_name Oct 20 '12 at 14:18
  • One addition to @cale_b's comment. `inline-block` in this case is not supported by IE < 8. [Source](http://caniuse.com/#search=%20inline-block) – PeeHaa Oct 20 '12 at 14:21
  • @PeeHa - that's not correct. There is an excellent hack that causes `inline-block` to be supported in older IE: http://uncorkedstudios.com/2011/12/12/how-to-fix-the-ie7-and-inline-block-css-bug/ – random_user_name Oct 20 '12 at 14:23
  • Sounds a bit "hacky" to me ;-) – PeeHaa Oct 20 '12 at 14:25
  • What browsers to you need to support here? `inline-block` is fine for IE8. It is also supported in IE7 (albeit with bugs), and for IE6 you can use `display:inline` instead, with a CSS hack to make it IE6-specific. Alternatively, if you want to stick with floats, if you can live with only IE8 and up, put the `clear:both` into the last element's `:after` selector; no more need for the extra clearing div. – Spudley Oct 20 '12 at 14:29
  • 1
    @PeeHaa - it is hacky. Totally agreed. That's why we all love old IE browsers.... – random_user_name Oct 20 '12 at 14:38

4 Answers4

11

You can use a clearfix:

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

and apply that to both the ul and the header.

PeeHaa
  • 71,436
  • 58
  • 190
  • 262
Brian
  • 2,819
  • 4
  • 24
  • 30
2

Better css for your situation would be (Tested in FF, Chrome, IE6+)

header {
    display: block; /* Necessary for older browsers to render this html5 element properly */
    background: #888;  
    height: 20px;  
    padding: 10px;  
}

ul {  
    margin: 18px 0;  
    padding: 0;  
    list-style: none;  
}

ul li {
    margin: 0 10px 0 0; /* at least some margin-right is necessary to make inline-block work in IE */
    padding: 0 5px; /* you don't have to set a width any longer, so let padding define spacing */
    display: inline-block;
    zoom: 1; /* part 1 of the IE hack to make inline-block work */
    *display: inline; /* part 2 of the IE hack to make inline-block work */
   /* height and line-height not necessary - driven by a element below */
    border: 1px solid #000;
    background: red;
}

ul li a {
    display:block;
    height: 20px;
    line-height: 20px; /* this will vertically center the text in the li */
    text-decoration: none;
    text-align: center;
}

ul li a:hover{
    color: #fff;
    background-color: #000;
}​
random_user_name
  • 25,694
  • 7
  • 76
  • 115
2

Rather than use a cleardiv, perhaps you could try the standard clearfix from html5boilerplate?

Here is the modified markup:

  <header class="clearfix">
      <ul>
          <li><a href='#'>Item 1</a></li>
          <li><a href='#'>Item 2</a></li>
          <li><a href='#'>Item 3</a></li>
          <li><a href='#'>Item 4</a></li>
      </ul>
  </header>

and here is the css to add:

.clearfix:before,
.clearfix:after {
    content: " "; /* 1 */
    display: table; /* 2 */
}

.clearfix:after {
    clear: both;
}


.clearfix {
    *zoom: 1;
}

From the docs:

.clearfix

Adding .clearfix to an element will ensure that it always fully contains its floated children. There have been many variants of the clearfix hack over the years, and there are other hacks that can also help you to contain floated children, but the HTML5 Boilerplate currently uses the micro clearfix.

Community
  • 1
  • 1
1

You can't use /> for divs. Change it from <div class='clear'/> to <div class="clear"></div>

Or try adding another li below the current ones and giving that the clear class.

<header>
    <ul>
        <li><a href='#'>Item 1</a></li>
        <li><a href='#'>Item 2</a></li>
        <li><a href='#'>Item 3</a></li>
        <li><a href='#'>Item 4</a></li>
        <li class='clear'></li>
    </ul>
</header>