一杯🍵的时间~了解css父元素坍塌问题+BFC

443 阅读5分钟

绪论

想必各位前端大佬在写样式的时候都会遇见这样的问题:样式写的好好的,怎么就出现了坍塌?那么这篇文章就来说明一下css父元素高度坍塌的问题以及解决办法

场景复现

首先我们要知道,在我们没有给父级块级元素高度时,父级元素的高度是由未浮动的子元素撑起来的,子元素也是按照标准的文档流进行排列,但是当我们将子元素进行浮动的时候就会脱离了标准文档流,这个时候就没有东西撑着父元素,就会造成父元素的高度塌陷,也就是下面图片展示的这样

image.png

可以看到,当我们给了子元素浮动以后父元素出现了高度塌陷,出现了高度坍塌会影响父元素的样式以及父元素外的元素布局的位置。

问题解决

综上所述,塌陷导致的问题我们是一定要解决的,那么如何解决呢?别急,先小酌一口,往下看!

为父元素设置 overflow:hidden 属性

原理:该属性强制要求父元素包裹住所有的内部浮动的元素
缺点:超出父元素的子元素不一定总是需要隐藏的,因此这个方法的缺陷就是溢出部分无法显示

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box {
        width: 100px;
        border: 1px solid #ccc;
        overflow: hidden;
      }
      .child {
        width: 20px;
        height: 100px;
        background: pink;
        float: left;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <div class="child"></div>
    </div>
  </body>
</html>

父元素内结尾追加空子元素设置clear:both 清除浮动

原理:利用clear:both属性和父元素必须包含非浮动的元素
缺点:多出无意义的一个空元素,影响选择器查找

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box {
        width: 100px;
        border: 1px solid #ccc;
      }
      .child {
        width: 20px;
        height: 100px;
        background: pink;
        float: left;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <div class="child"></div>
      <div style="clear: both"></div>
    </div>
  </body>
</html>

让父元素也浮动起来

原理:浮动属性会强制父元素扩大包含所有浮动的内部元素
缺点:父元素浮动,也脱离了文档流,导致布局混乱,可以通过给后续元素添加清除浮动属性解决

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      .container {
        width: 90%;
        margin: 100px auto;
        text-align: center;
      }
      .box {
        width: 100%;
        border: 1px solid #ccc;
        float: left;
      }
      .child {
        width: 80%;
        height: 100px;
        background: pink;
        float: left;
      }
      .footer {
        width: 100%;
        height: 40px;
        background: #ececec;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="box">
        <div class="child"></div>
        <div></div>
      </div>
      <div class="footer"></div>
    </div>
  </body>
</html>

为父元素末尾伪元素设置clear:both属性

这种办法相对之前的办法比较来看相对完美,不会出现移除元素隐藏,不方便查找元素以及产生新的浮动的问题

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        padding: 0;
        margin: 0;
      }
      .container {
        width: 90%;
        margin: 100px auto;
        text-align: center;
      }
      .box {
        width: 100%;
        border: 1px solid #ccc;
      }
      .child {
        width: 80%;
        height: 100px;
        background: pink;
        float: left;
      }
      .footer {
        width: 100%;
        height: 40px;
        background: #ececec;
      }
      .box::after {
        content: '';
        display: table;
        clear: both;
        height:0; /*防止有些浏览器设置displa:table有默认高度*/
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="box">
        <div class="child"></div>
        <div></div>
      </div>
      <div class="footer"></div>
    </div>
  </body>
</html>

通过上述描述可以发现,在设置overflow:hidden和使用父元素float时都会强制父元素包裹内部浮动元素,解决高度塌陷问题,聪明的小伙伴就会问这是为什么呢?这就引出了我们要讲的另一个知识点——BFC

加餐环节——了解BFC

什么是BFC?(Block formatting context)

BFC又称块级格式化上下文,是网页中独立的一个渲染区域,这个渲染区域只有块级元素可以参与,与此同时,BFC也规定了内部块级元素如何布局,BFC内部渲染与外部毫无关系。
举个🌰:大家都看过施工场地,蓝色的隔断将内部与外部区分开来,栅栏内部就好比BFC渲染的区域,隔断里面如何施工是与外面没有关系的,就好比BFC内部的渲染与其外部毫无关系
我们也可以这样记:BFC是独立渲染区域,内部不影响外部。外部不影响内部。

详细说说

其实在CSS中有两种渲染区域,第一种是块级渲染区域,所有display属性为blocktablelist-item的元素会生成块级渲染区域,块级渲染区域以BFC的渲染规则进行内部渲染,从上到下依次排列;第二种是行内渲染区域,又称IFC,其布局方式是水平依次排列。

BFC的布局规则

  • 默认内部块级元素垂排列
  • 块元素垂直方向总距离是由边框内大小 + margin决定的
  • 属于同一个BFC两个相邻的块元素的垂直margin会重叠,左右不会
  • 计算父元素高度时,内部浮动元素都要算在内

如何形成BFC?

MDN中已经有详细介绍,这里呈上几条供参考

  • float不为none
  • position不为static或relative
  • display值为table-cell、table-caption、table等
  • overflow值不为visible

阶段总结

讲到这里大家应该明白上面提出问题的原因了,使用floatoverflow后父元素形成BFC,因为BFC的规则,强制包含内部所有浮动元素,所以就解决了高度塌陷问题。

使用BFC解决更多问题

当然BFC不仅仅能解决高度塌陷问题,他还有 其他的好用处!

使用BFC避免垂直方向的margin合并

当两个块级元素垂直排列并具有垂直方向的margin时,会取大的一方进行margin合并,使用BFC可以避免这一问题,相当于在两个块级元素之间插入一堵墙,上下互不干扰

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box1 {
        width: 100px;
        height: 100px;
        border: 1px solid #ccc;
        margin-bottom: 50px;
      }
      .bfc {
        display: table;
      }
      .box2 {
        margin-top: 150px;
        width: 100px;
        height: 100px;
        border: 1px solid #ccc;
      }
    </style>
  </head>
  <body>
    <div class="box1"></div>
    <div class="bfc"></div>
    <div class="box2"></div>
  </body>
</html>

使用BFC解决垂直方向的margin溢出

有这样一个场景,父元素中的子元素给予margin-top,但实际效果是父级元素给跟着向下移动了

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .box1 {
        width: 300px;
        height: 400px;
        background: sandybrown;
        overflow: hidden
      }
      .box2 {
        width: 100px;
        height: 20%;
        background: pink;
        margin-top: 100px;
      }
    </style>
  </head>
  <body>
    <div class="box1">
      <div class="box2"></div>
    </div>
  </body>
</html>

这时我们就可以使用BFC解决,这里我就用给父元素添加overflow:hidden作为一种生成BFC的方式举例

茶后总结

相信大佬们通过阅读已经充分了了解解决塌陷问题的方法以及BFC的相关内容,如果各位伙伴觉得有帮助的话希望用你们可爱的小手点赞支持!如果哪里写的有问题也希望帮笔者提出,我会及时改正的哦~,好啦,茶已喝完,继续干活喽!