如何解决高度坍塌问题?——BFC模式

来源:那些年我们一起清除的浮动

   CSS|Float知多少

     学习块格式化上下文

问题引起是2016IFE春季问题的任务三,总的父元素parent包含三个浮动的子元素,容器的高度不能自动伸长以适应内容的高度,出现了高度坍塌问题。

代码如下:

<div class="parent">
           <div class="left"></div>
           <div class="center"></div>
           <div class="right"></div></div>

       .parent{

           margin:20px;

           background-color:red;

           border:solid 2px black;

        }

        .left,.right,.center{

            float:left;

            width:200px;

            height:200px;

            background-color:yellow;

            border:solid 2px blue;

        }

(最上面的一条黑线就是parent元素了,可以看到它的高度为0)

   原因就是浮动使子元素脱离文档流,父元素无法感知子元素的存在,而且父元素内部不存在其他处于文档流中的元素,也就表现为高度为0。

既然是由浮动引起的,就用clear属性清除浮动吧,其实这是错误的,clear属性规定的是元素哪一侧不允许有其他浮动元素,但是我们并不是想让父元素周围没有其他浮动元素,而是减少浮动带来的影响,也就是使浮动元素闭合。

先来看一下闭合浮动的方法:

      1)添加额外标签

         通过在浮动元素末尾添加一个空的标签,例如 <div style=”clear:both”></div>,其他标签br等亦可。      

<div class="wrap" id="float1">

  <h2>1)添加额外标签</h2>

  <div class="main left">.main{float:left;}</div>

  <div class="side left">.side{float:right;}</div>

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

</div>

<div class="footer">.footer</div>

优雅的 Demo

        优点:通俗易懂,容易掌握

         缺点:可以想象通过此方法,会添加多少无意义的空标签,有违结构与表现的分离,在后期维护中将是噩梦,这是坚决不能忍受的,所以你看了这篇文章之后还是建议不要用了吧。

     2)使用 br标签和其自身的 html属性

        这个方法有些小众,br 有 clear=“all | left | right | none” 属性

<div class="wrap" id="float2">

  <h2>2)使用 br标签和其自身的 html属性</h2>

  <div class="main left">.main{float:left;}</div>

  <div class="side left">.side{float:right;}</div>

  <br clear="all" />

</div>

<div class="footer">.footer</div>

优雅的 Demo

         优点:比空标签方式语义稍强,代码量较少

       缺点:同样有违结构与表现的分离,不推荐使用

      3)父元素设置 overflow:hidden

       通过设置父元素overflow值设置为hidden;在IE6中还需要触发 hasLayout ,例如 zoom:1;

<div class="wrap" id="float3" style="overflow:hidden; *zoom:1;">

  <h2>3)父元素设置 overflow </h2>

  <div class="main left">.main{float:left;}</div>

  <div class="side left">.side{float:right;}</div>

</div>

<div class="footer">.footer</div>

优雅的 Demo

  优点:不存在结构和语义化问题,代码量极少

       缺点:内容增多时候容易造成不会自动换行导致内容被隐藏掉,无法显示需要溢出的元素;04年POPO就发现overflow:hidden会导致中键失效,这是我作为一个多标签浏览控所不能接受的。所以还是不要使用了

      4)父元素设置 overflow:auto 属性

       同样IE6需要触发hasLayout,演示和3差不多

       优点:不存在结构和语义化问题,代码量极少

       缺点:多个嵌套后,firefox某些情况会造成内容全选;IE中 mouseover 造成宽度改变时会出现最外层模块有滚动条等,firefox早期版本会无故产生focus等, 请看 嗷嗷的 Demo ,不要使用

      5)父元素也设置浮动

       优点:不存在结构和语义化问题,代码量极少

       缺点:使得与父元素相邻的元素的布局会受到影响,不可能一直浮动到body,不推荐使用

      6)父元素设置display:table

       优雅的 Demo

       优点:结构语义化完全正确,代码量极少

        缺点:盒模型属性已经改变,由此造成的一系列问题,得不偿失,不推荐使用

      7)使用:after 伪元素

        需要注意的是 :after是伪元素(Pseudo-Element),不是伪类(某些CSS手册里面称之为“伪对象”),很多闭合浮动大全之类的文章都称之为伪类,不过csser要严谨一点,这是一种态度。

        由于IE6-7不支持:after,使用 zoom:1触发 hasLayout。

         该方法源自于: How To Clear Floats Without Structural Markup

        最后精简的代码如下:

           .clearfix:after {content:".";    生成内容作为最后一个元素,至于content里面是点还是其他都是可以的

                display:block; 使生成的元素以块级元素显示,占满剩余空间;

                 height:0;  避免生成内容破坏原有布局的高度。

                 visibility:hidden; 使生成的内容不可见,并允许可能被生成内容盖住的内容可以进行点击和交互;

                  clear:both;  闭合浮动

                  }

          .clearfix { *zoom:1; }      触发IE hasLayout。

 小结

    通过对比,我们不难发现,其实以上列举的方法,无非有两类:

    其一,通过在浮动元素的末尾添加一个空元素,设置 clear:both属性,after伪元素其实也是通过 content 在元素的后面生成了内容为一个点的块级元素;

    其二,通过设置父元素 overflow 或者display:table 属性来闭合浮动,我们来探讨一下这里面的原理。

     原理就是 Block formatting contexts(块级格式化上下文),以下简称 BFC,它是CSS2.1规范定义的,是页面 CSS 视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域。简单来说,BFC 就是一种属性,这种属性会影响着元素的定位以及与其兄弟元素之间的相互作用。

下面的情况会产生新的BFC:

  • 根元素或其它包含它的元素
  • 浮动 (元素的 float 不为 none)
  • 绝对定位元素 (元素的 position 为 absolute 或 fixed)
  • 行内块 inline-blocks (元素的 display: inline-block)
  • 表格单元格 (元素的 display: table-cell,HTML表格单元格默认属性)
  • 表格标题 (元素的 display: table-caption, HTML表格标题默认属性)
  • overflow 的值不为 visible的元素
  • 弹性盒 flex boxes (元素的 display: flex 或 inline-flex)

    其中,最常见的就是overflow:hidden、float:left/right、position:absolute。也就是说,每次看到这些属性的时候,就代表了该元素已经创建了一个BFC了。

    需要注意的是,display:table 本身并不会创建BFC,但是它会产生匿名框(anonymous boxes  , 没有名字不能被选择器选中的盒,它们的所有属性都为inherit或初始默认值;),而匿名框中的display:table-cell可以创建新的BFC,换句话说,触发块级格式化上下文的是匿名框,而不是display:table。所以通过display:table和display:table-cell创建的BFC效果是不一样的。

 BFC的 特性

  BFC包含创建该上下文元素的所有子元素,但不包括创建了新BFC的子元素的内部元素,也就是一个元素不能同时存在于两个BFC中。

通俗地来说:创建了 BFC的元素就是一个独立的盒子,里面的子元素不会在布局上影响外面的元素,反之亦然,同时BFC仍然属于文档中的普通流。

  1. 内部的盒会在垂直方向一个接一个排列(可以看作BFC中有一个的常规流);
  2. 处于同一个BFC中的元素相互影响,可能会发生外边距叠加,如果这两个相邻的块框不属于同一个块级格式化上下文,那么它们的外边距就不会叠加。;
  3. 每个元素的margin box的左边,与容器块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此;
  4. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
  5. 计算BFC的高度时,考虑BFC所包含的所有元素,连浮动元素也参与计算;
  6. 浮动盒区域不叠加到BFC上;

 从实际代码来分析BFC

实例一

<style>
    * {
        margin: 0;
        padding: 0;
    }
    .left{
        background: #73DE80;    /* 绿色 */
        opacity: 0.5;
        border: 3px solid #F31264;
        width: 200px;
        height: 200px;
        float: left;
    }
    .right{                     /* 粉色 */
        background: #EF5BE2;
        opacity: 0.5;
        border: 3px solid #F31264;
        width:400px;
        min-height: 100px;
    }
    .box{
        background:#888;
        height: 100%;
        margin-left: 50px;
    }
</style>
<div class=‘box‘>
    <div class=‘left‘> </div>
    <div class=‘right‘> </div>
</div>

显示效果:

  绿色框(‘#left‘)向左浮动,它创建了一个新BFC,但暂时不讨论它所创建的BFC。由于绿色框浮动了,它脱离了原本normal flow的位置,因此,粉色框(‘#right‘)就被定位到灰色父元素的左上角(特性3:元素左边与容器左边相接触),与浮动绿色框发生了重叠。

同时,由于灰色框(‘#box‘)并没有创建BFC,因此在计算高度的时候,并没有考虑绿色框的区域,发生了高度坍塌,这也是常见问题之一。

实例二

现在通过设置overflow:hidden来创建BFC闭合浮动,再看看效果如何。

.BFC{
    overflow: hidden;
}

<div class=‘box BFC‘>
    <div class=‘left‘> </div>
    <div class=‘right‘> </div>
</div>

  灰色框创建了一个新的BFC后,高度发生了变化,计算高度时它将绿色框区域也考虑进去了(特性5:计算BFC的高度时,浮动元素也参与计算);

而绿色框和红色框的显示效果仍然没有任何变化。

实例三

现在,现将一些小块添加到粉色框中,看看效果:

<style>
    .little{
        background: #fff;
        width: 50px;
        height: 50px;
        margin: 10px;
        float: left;
    }
</style>

<div class=‘box BFC‘>
    <div class=‘left‘> </div>
    <div class=‘right‘>
        <div class=‘little‘></div>
        <div class=‘little‘></div>
        <div class=‘little‘></div>
    </div>
</div>

  由于粉色框没有创建新的BFC,因此粉色框中白色块受到了绿色框的影响,被挤到了右边去了(特性6:浮动盒区域不叠加到BFC上)。先不管这个,看看白色块的margin,发生了外边距叠加。

实例四

利用同实例二中一样的方法,为粉色框创建BFC,防止与浮动元素(绿色框)重叠:

<div class=‘box BFC‘>
    <div class=‘left‘> </div>
    <div class=‘right BFC‘>
        <div class=‘little‘></div>
        <div class=‘little‘></div>
        <div class=‘little‘></div>
    </div>
</div>

  一旦粉色框创建了新的BFC以后,粉色框就不与绿色浮动框发生重叠了,同时内部的白色块处于隔离的空间(特性4:BFC就是页面上的一个隔离的独立容器),白色块也不会受到绿色浮动框的挤压。

总结

  以上就是BFC的分析,BFC的概念比较抽象,但通过实例分析应该能够更好地理解BFC。在实际中,利用BFC可以闭合浮动(实例二),防止与浮动元素重叠(实例四)。同时,由于BFC的隔离作用,可以利用BFC包含一个元素,防止这个元素与BFC外的元素发生margin collapse。

为什么坍塌?

  float 脱离了普通流,并且创建了新的BFC,而父元素不具备产生 BFC 的条件,所以它的高度为0。

如何解决?

  通过了解BFC的特性我们知道,BFC会把它包含的浮动元素高度也算在里面,也就是闭合浮动。拿 overflow: auto 举例:

  overflow: auto 并不会闭合浮动,而是 overflow: auto 会创建一个新的BFC,避免浮动的元素侵入其他元素。

  IE6-7有一个特有的属性就是haslayout当一个元素的hasLayout属性值为true时,我们说这个元素有一个布局(layout),它负责对自己和可能的后代元素进行尺寸计算和定位,当属性值为false时,它的尺寸和位置由最近拥有布局的祖先元素控制。

触发hasLayout的条件:

  • position: absolute
  • float:
    left|right
  • display:
    inline-block
  • width:
    除 “auto” 外的任意值
  • height:
    除 “auto” 外的任意值 (例如很多人闭合浮动会用到
    height: 1%  )
  • zoom:
    除 “normal” 外的任意值
  • writing-mode:
    tb-rl

在 IE7 中,overflow 也变成了一个 layout 触发器:

  • overflow:
    hidden|scroll|auto ( 这个属性在IE之前版本中没有触发
    layout 的功能。 )
  • overflow-x|-y:
    hidden|scroll|auto (CSS3
    盒模型中的属性,尚未得到浏览器的广泛支持。他们在之前IE版本中同样没有触发
    layout 的功能)

综上所述:

 在支持BFC的浏览器(IE8+,firefox,chrome,safari)通过创建新的BFC闭合浮动;

 在不支持 BFC的浏览器 (IE6-7),通过触发
hasLayout 闭合浮动。

 

时间: 2024-11-07 10:39:07

如何解决高度坍塌问题?——BFC模式的相关文章

解决高度坍塌问题(二)

我们了解完高度坍塌问题之后,那么如何去解决高度坍塌问题呢? 解决高度问题的方法一: 解决问题的原理:根据W3C标准,元素都有一个隐含的属性(Block Formatting Context)简称BFC,块级格式化环境,该属性可以设置打开或是关闭,当开启BFC后,元素将会具有如下特性: 1.父元素的垂直外边距不会和子元素重叠. 2.开启BFC的元素不会被浮动元素覆盖. 3.开启BFC的元素可以包含浮动的子元素. 方案一:直接为父元素指定高度,假设子元素是200px,那么就为父元素的高度也设置为20

高度塌陷问题以及如何解决高度坍塌问题

      我们在进行页面布局的时候可以发现元素在脱离文档流后,就会出现高度塌陷问题. 一.什么是高度塌陷? 通过下面的例子了解什么是高度塌陷. 在页面中设置一个盒子box,其中在嵌套一个子元素小盒子box1.box设置边框宽度,而高度不去设置(高度会由内容撑开) 但是当我们向盒子里面添加内容的时候<div class="box1">a</div>,就可以发现父元素被撑开了. 在文档流定位中,父元素的高度默认是被子元素撑开的高度.即子元素的高度就是父元素的高度.

如何解决高度塌陷

hello 朋友们,我又来了哦!对的没错,今天的话题呢就是高度塌陷. 首先要知道什么是高度塌陷.高度塌陷其实就是指当父元素没有给确定的高度(即父元素高度靠子元素撑起来),并且子元素添加了浮动时,内容无法撑起父元素的高度,即父元素发生高度塌陷. 解决办法: 第一种,开启元素的BFC,元素将会具有如下的特性: 1.父元素的垂直外边距不会和子元素重叠 2.开启BFC的元素不会被浮动元素所覆盖 3.开启BFC的元素可以包含浮动的子元素 开启元素BFC属性的方式: 一.给父元素添加声明,清除浮动 over

JS组件系列——自己动手扩展BootstrapTable的 冻结列 功能:彻底解决高度问题

前言:一年前,博主分享过一篇关于bootstrapTable组件冻结列的解决方案  JS组件系列——Bootstrap Table 冻结列功能IE浏览器兼容性问题解决方案 ,通过该篇,确实可以实现bootstrapTable的冻结列效果,并且可以兼容ie浏览器.这一年的时间,不断有园友以及群里面的朋友问过我关于固定高度之后,冻结列页面效果不能对齐的问题,奈何博主太忙,一直没有抽空将这个问题优化.最近项目里面也不断有人提过这个bug,这下子不能再推了,必须要直面“惨淡的bug”,于是昨天利用一天的

IE6不支持min-height如何解决高度自适应问题

IE6不支持min-height如何解决高度自适应问题:建议:尽可能的手写代码,可以有效的提高学习效率和深度.IE6问题多多,给大家带来了诸多烦恼,这里介绍一下因为IE6浏览器不支持min-height属性,从而导致了高度无法自适应的问题.在其他标准浏览器中,我们可以使用min-height属性给容器规定一个最小高度,如果内容超过这个最小高度,容器会自动被撑开以达到高度自适应效果,但是IE6浏览器并不支持这个属性,不过IE6本身就有高度自适应的特点,或许大家会认为只要同时使用height和min

解决float之后容器高度坍塌

在使用float属性的时候,我们经常会遇到这样的问题,当元素的设置了float,而父容器的高度就坍塌了,如下效果 法国球星亨利宣布退役之后,国际足坛大腕们纷纷对他表示敬意,尤其是他以前效力的阿森纳队众球星都称赞他为“传奇人物.” 国际足联主席布拉特也发表推文说:“衷心祝福亨利.很遗憾看到一位世界冠军离开了赛场,但也高兴你仍然距离足球非常近.” 亨利在2007年离开阿森纳后,沃尔科特继承了他的14号球衣,这位17岁就入选英格兰队的边锋在推特上说:“在我的职业生涯中,你一直在激励我.感谢蒂埃里·亨利

float浮动问题:会造成父级元素高度坍塌;

解决办法:清除浮动:clear:both; 给父元素高度:height(不是很可取) 给父元素:display:inline-black:(问题:margin:auto失效) 给父元素:overflow:hidden;( 在IE67需要有宽度); 给父元素添加伪类;:after{content:""; display:block:clear:both;} (万能)

修改Nginx解决ThinkPHP不支持PathInfo模式

最精简的Nginx配置 server { listen 80; server_name test.com; charset utf-8; location / { root E:/WWW/test; index index.php; if (!-e $request_filename) { #一定要用(.*)匹配整个URI,包含URI第一个字符反斜杠/ #rewrite ^(.*)$ /index.php?s=$1 last; rewrite ^/(.*)index.php(.*)$ $1/in

解决chrome在ubuntu+root模式下打不开的问题

chrome在ubuntu root模式下打不开 双击图标,chrome打不开了: 解决办法: 查看一下打开chrome浏览器的命令是什么,右键properties 发现是chromium-browser %U,将该命令粘贴到命令行运行看一下错误提示: root模式下不加 --no-sandbox选项运行是不允许的. 因此我们在properties中加入--no-sandbox选项 然后使用该图标就可以打开chrome了 #####################################