CSS overflow:hidden with floats

2019-01-01 16:07发布

问题:

I read the following code on w3schools and do not understand how the overflow property would impact whether text appears to the right of the ul or not.

ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

li {
  float: left;
}

a {
  display: block;
  width: 60px;
  background-color: #dddddd;
  padding: 8px;
}
<ul>
  <li><a href=\"#home\">Home</a></li>
  <li><a href=\"#news\">News</a></li>
  <li><a href=\"#contact\">Contact</a></li>
  <li><a href=\"#about\">About</a></li>
</ul>
<p><b>Note:</b> overflow:hidden is added to the ul element to prevent li elements from going outside of the list.</p>

I know that overflow:hidden is used to handle content that goes outside of the box but don\'t understand how it applies in this instance.

回答1:

I try to end the confusion:

ul is a block-level element as is the p element (they stretch to 100% of the parent width). That is why per default the p will appear below the ul if no width or display is declared on those elements.

Now in your example the ul contains only floated elements. This makes it collapse to a height of 0px (It still has 100% width though as you can see in the example). The adjacent p will appear to the right of the floated lis because they are considered as normal floated elements.

Now declaring overflow (any value other than visible) establishes a new block formatting context, which makes the ul contains its children. Suddenly the ul \"reappears\", not having size 0px anymore. The p is getting pushed to the bottom. You could also declare position:absolute to achieve the same \"clearing\" effect (with the side effect that now the ul is taken out of the normal element flow - the ps will be overlapped by the ul.)

See the example fiddle

If you are into the technical stuff, compare the according paragraphs of the CSS spec:

§10.6.3 Block-level non-replaced elements in normal flow when \'overflow\' computes to \'visible\'
and
§10.6.7 \'Auto\' heights for block formatting context roots. (Thanks to BoltClock for digging out the links).

ul{
    list-style-type:none;
    margin:0; padding:0;
    background-color:#dddddd;
    border:2px solid red;
}
li{
    float:left;
}
a{
    display:block;
    width:60px;
    background-color:#555;
    color:white;
}
p{
    margin:0;
    outline:2px dotted blue;
}
#two{
    clear:both;
    overflow:hidden;
}
No overflow:
<ul>
<li><a href=\"#home\">Home</a></li>
<li><a href=\"#news\">News</a></li>
<li><a href=\"#contact\">Contact</a></li>
<li><a href=\"#about\">About</a></li>
</ul>
<p>Notice the collapsed ul - no background-color visible, collapsed border and this paragraph treats the lis as regular floats  </p>
<br>
With overflow: hidden
<ul id=\"two\">
<li><a href=\"#home\">Home</a></li>
<li><a href=\"#news\">News</a></li>
<li><a href=\"#contact\">Contact</a></li>
<li><a href=\"#about\">About</a></li>
</ul>
<p>the ul reappeared - it now contains the child li\'s - the float is cleared</p>



回答2:

Setting overflow: hidden on an element causes a new float context to be created, so elements that are floated inside an element that has overflow: hidden applied are cleared.

http://www.w3.org/TR/CSS2/visuren.html#block-formatting



回答3:

This is why w3schools is not a reliable source for web designer/developers. You are correct, it is a terrible example.

It doesn\'t because, in this example, the parent element does not have a fixed with. Furthermore, it\'s an un-ordered list tag, which is going to stretch to the size of it\'s children regardless.

http://jsfiddle.net/EhphH/

CSS

.parent {
    width: 150px;
    height: 100px;
    padding: 10px;
    background: yellow;
    overflow: hidden;

}
.child {
    float: left;
    width: 75px;
    height: 120px;
    margin: 10px;
    background: blue;

}
.baby {
    width: 200px;
    height: 25px;
    background: green;
}

Markup

<div class=\"parent\">
    <div class=\"child\">
        <div class=\"baby\">
        </div>
    </div>
    <div class=\"child\">
    </div>
</div>


回答4:

Instead of the overflow:hidden; use clear:both; for the <p>. here it is in use http://jsfiddle.net/Mvv8w/. Basically overflow:hidden will clear anything that is aside it just as clear:both; does.