浮动引起的高度塌陷问题及其解决

263 阅读5分钟

1、浮动引起的高度塌陷

  • 由于浮动元素脱离了标准流,变成了脱标元素,所以不再像父元素汇报宽度和高度;

    • 父元素在计算高度的时候,就会将其包含的子元素中设置了浮动的子元素的高度忽略不计,从而导致父元素高度的塌陷;
  • 下面通过一个实验来验证一下:

  • html结构如下:

<body>
   <div class="container">
       <div class="item item1">1</div>
       <div class="item item2">2</div>
       <div class="item item3">3</div>
       <div class="item item4">4</div>
   </div>
</body>
  • 对应的CSS样式如下:
body {
   margin: 0;
}

.container {
  width: 500px;
  margin: 0 auto;   /*使其始终在浏览器页面居中,方便观察*/
  color: #fff;
  background-color: orange;
}

.container > .item {
   width: 110px;
   height: 120px;
   float: left;
}

.container > .item1 {
    background-color: pink;
}

.container > .item2 {
    background-color: red;
}

.container > .item3 {
    background-color: blue;
}

.container > .item4 {
    background-color: green;
}
  • 梳理一下元素之间的关系可以得到如下的关系图:

image.png

  • 即块级元素div包裹了四个浮动元素,那么理论上来说块级元素的高度是由其包裹的内容所支撑起来,所以我们没有给这个父级div元素设置高度。同时我们给该父级div元素设置了背景色橘色,方便观察,下面看下效果;

image.png

  • 可以看到父级元素div完全消失不见了。因为父级元素的宽度设置为500px,而每一个浮动元素的宽度是110px,又因为浮动元素在排列的时候是相互之间紧挨着的,所以加起来一定是440px的宽度,如果父级元素能显示的话,其必定会在绿色的旁边显示处一部分,但并没有,所以这时父级div元素的高度就发生了坍塌

  • 同时Chrome浏览器调试工具也显示其高度为0;

image.png

2、解决浮动引起的高度塌陷的方案

  • 清除浮动

    • 可以解决父元素高度塌陷的问题,让父元素在计算总高度的时候,重新将浮动子元素的高度计算进去
  • 如何清除浮动

    • 使用CSSclear属性;
  • clear属性的作用

    • 可以指定一个元素是否必须移动到它之前的浮动元素的下面
  • 四个值:

    • 1、left: 移动到在它前面设置了向左浮动的元素的后面;
    • 2、right: 移动到在它前面设置了向右浮动的元素的后面;
    • 3、both: 移动到在它前面设置了浮动的所有元素的后面;
    • 4、none: 默认值,相当于不设置clear这个属性;
  • 下面来解决一下前面高度塌陷的问题 ( 代码与上面不同的部分会标记出来 )

 <body>
   <div class="container">
       <div class="item item1">1</div>
       <div class="item item2">2</div>
       <div class="item item3">3</div>
       <div class="item item4">4</div>
       
       <div class="clear-float"></div>   <!-- 增加的语句 -->
   </div>
body {
   margin: 0;
}

.container {
  width: 500px;
  margin: 0 auto;   /*使其始终在浏览器页面居中,方便观察*/
  color: #fff;
  background-color: orange;
}

.container > .item {
   width: 110px;
   height: 120px;
   float: left;
}

.container > .item1 {
    background-color: pink;
}

.container > .item2 {
    background-color: red;
}

.container > .item3 {
    background-color: blue;
}

.container > .item4 {
    background-color: green;
}

/* 增加的语句 */
.container > .clear-float {
 clear: both;
}
  • 在父级div元素中,所有浮动元素后面增加一个div元素,div元素的宽度默认独占父级div元素的一行,同时没有对该div元素设置高度,并且其没有包含内容,所以高度为0。但由于对其设置了clear: both;,所以其会被移动到在它前面设置了浮动的元素的后面。也就是说,其在标准流中有宽度但是没有高度,并且占据标准流中的父级div元素(父级div元素并没有脱离标准流)的最后行的位置(没有高度所以不显示)。那么此时因为块级元素的高度是由其内容撑起来的,而在div.container中,div.clear-float被放到了所有浮动元素之后,所以此时浮动元素的高度被重新计算入父元素的高度中,而div.clear-float的高度为0,所以div.container的高度就是浮动元素的高度,为120px;

  • 从结果图也可以看到,父级div元素的橘色背景色显出来了;

image.png

  • 同时Chrome浏览器调试工具也显示其高度为120px;

image.png

3、改进

  • 刚才高度塌陷的问题实际上是由CSS设置浮动引起的,属于CSS的问题但是却在html中增加了一个div元素解决不太符合网页设计中结构与样式分离的原则;而且浮动布局也算是flex布局出现前面非常常用的网页的多列布局方案,至今有网站还在使用;

  • 所以能不能仅仅通过CSS样式来解决,这样的话在需要解决高度塌陷的问题的时候仅仅需要添加一个编写好的CSS样式就行了,这样通用性就非常强。

    • 这里就要用到伪元素了, 下面来编写一个解决高度塌陷的CSS样式:
    .clear-float::after {
        content: "";
        display: block;     /*这句一定要加,如果不加的话,默认伪元素是行内非替换元素,因为已经没有内容了,相当于就不占位置了。所以设置其为块级元素,至少有个默认的宽度,就会占据位置,才能让设置了的clear有用*/
        clear: both;
    }
  • 这样的话就解决了高度塌陷的问题,并且只要有因为浮动引起的高度塌陷的问题的话,就可以把上面这段CSS代码引入该HTML中,并且给高度塌陷的父级元素(包含块)添加一个名为.clear-floatclass即可解决

  • 对于我们的代码就是:

<div class="container clear-float">
    <!--中间省略,与前面相同-->
</div>

4、通用性更强的解决高度塌陷的CSS样式代码

.clear-float::after {
  content: "";
  display: block;
  clear: both;
  
  visibility: hidden;   /*浏览器兼容性*/
  height: 0;  /*浏览器兼容性*/
}

.clear-float {
  *zoom: 1;  /*IE6/7兼容性*/
}