CSS不可不知,摘自网摘

CSS 属性flow-root

2017/04/26 · CSS · flow-root

原文出处: 大漠   

今天我们来介绍CSS中的一个新属性flow-root。这个属性是CSS Display Module Level3中的一个属性。简单讲这个属性是display中的一个新属性,对于display属性,大家熟悉的可能是常见的几个属性,比如block、inline、inline-block、flex、grid、table和table-cell等,其实除了这些常见的属性值之外,还有很多其他的值。如果想了解更多,那可以点击这里阅读。

那flow-root既然是display的新属性值,那这个属性值有什么特性呢?这就是今天要聊的东西。

清除浮动--全面解读(摘自网摘--那些年我们一起清除过的浮动),全面解读网摘

碎碎念


上一篇讨论浮动与清除浮动的博客中,最后提到了BFC(Block Formatting Contexts)的概念。

我建议每个学前端的人都要把BFC理解透彻,这样在解决外边距堆叠,高度塌陷及各种定位、布局带来的负面影响时,都能了解原理,选择恰当的解决办法。

废话不多说了,开始:P

如何触发BFC呢?

1、float 除了none以外的值
2、overflow 除了visible 以外的值(hidden,auto,scroll )
3、display (table-cell,table-caption,inline-block)
4、position(absolute,fixed)
5、fieldset元素

需要注意的是,display:table 本身并不会创建BFC,但是它会产生匿名框(anonymous boxes),而匿名框中的display:table-cell可以创建新的BFC,换句话说,触发块级格式化上下文的是匿名框,而不是display:table。所以通过display:table和display:table-cell创建的BFC效果是不一样的。

fieldset 元素在www.w3.org里目前没有任何有关这个触发行为的信息,直到HTML5标准里才出现。有些浏览器bugs(Webkit,Mozilla)提到过这个触发行为,但是没有任何官方声明。实际上,即使fieldset在大多数的浏览器上都能创建新的块级格式化上下文,开发者也不应该把这当做是理所当然的。CSS 2.1没有定义哪种属性适用于表单控件,也没有定义如何使用CSS来给它们添加样式。用户代理可能会给这些属性应用CSS属性,建议开发者们把这种支持当做实验性质的,更高版本的CSS可能会进一步规范这个。

BFC

在学习flow-root之前,咱们要先了解CSS中一个非常重要的概念,那就是BFC(Block Formatting Context)的概念。那什么是BFC呢?

在W3C规范中的BFC是这样定义的:

浮动元素和绝对定位元素,非块级盒子的块级容器(例如,inline-block、table-cells和table-captions),以及overflow值不为visiable的块级盒子,都会为他们的内容创建新的BFC(块级格式上下文)。

在BFC中,盒子从顶端开始垂直地一个接一个地排列,两个盒子之间的垂直的间隙是由他们的margin值所决定的。在一个BFC中,两个相邻的块级盒子的垂直外边距会产生折叠。

在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)。对于从右到左的格式来说,则触 碰到右边缘。

规范中的描述可能难让人理解,我们再来看看BFC的一种通俗理解:

首先BFC是一个名词,是一个独立的布局环境,我们可以理解为一个箱子(实际上是看不见摸不着的),箱子里面物品的摆放是不受外界的影响的。转换为BFC的理解则是:BFC中的元素的布局是不受外界的影响(我们往往利用这个特性来消除浮动元素对其非浮动的兄弟元素和其子元素带来的影响。)并且在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列

必竟这篇文章不是主要介绍CSS中的BFC的,如果你想深入的了解CSS中的BFC相关知识,可以阅读下面的文章:

  • 深入理解BFC和Margin Collapse
  • CSS layout入门
  • CSS深入理解流体特性和BFC特性下多栏自适应布局
  • 前端精选文摘:BFC 神奇背后的原理
  • 从莫名的熟悉到明确的概念:CSS BFC(Block Formatting Context)
  • BFC(块级格式化上下文)
  • CSS之BFC详解
  • CSS学习专题-BFC
  • Melon Space
  • 详说 Block Formatting Contexts (块级格式化上下文)
  • CSS中BFC的概念及外层div包裹内层div处理方法
  • How does the CSS Block Formatting Context work?
  • CSS 101: block formatting contexts
  • CSS 101: Block Formatting Contexts
  • 了解CSS中的块格式化上下文
  • 理解CSS中的块级格式化上下文
  • CSS中的BFC

一、清除浮动和闭合浮动

  所谓清除浮动,是指显示上正确。避免了文档流自动包裹浮动元素的特性(常见的是footer部分设置clear:both;属性);

而闭合浮动,是确实解决了高度塌陷的问题,使得wrap元素具有了高度。可疑包裹进浮动的元素。所以说,称之为闭合浮动更为合适。

官方文档对BFC的解释


首先,我们来看看官方文档是如何描述BFC的,我把这段定义拆成三小段,分段描述:

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

  • 浮动,绝对定位,不是块级盒的块级包含块(例如inline-block,table-cells和table-caption),及overflow值不为visible的块级盒子为他们的内容新的块级格式化上下文(BFC)

In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the 'margin' properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.

  • 在一个块级格式化上下文中,盒子是从包含块顶部开始,一个接一个的垂直排列。
  • 两个后代盒子的垂直距离由margin即外边距属性决定。
  • 在一个块级格式化上下文中,两个相邻的块级盒子外边距会折叠;

In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box's line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

  • 在一个块级格式化上下文中,每个盒子的外边距和其包含块的左边沿相接触(对于从右向左的格式则相反);
  • 即使在有浮动元素的存在,情况下也是如此(一个盒子的行盒会因为浮动而收缩),除非这个盒子建立了一个新的BFC(在某些情况下,这个盒子自身会变窄)

BFC的特性:

  1. 1块级格式化上下文会阻止外边距叠加

当两个相邻的块框在同一个块级格式化上下文中时,它们之间垂直方向的外边距会发生叠加。换句话说,如果这两个相邻的块框不属于同一个块级格式化上下文,那么它们的外边距就不会叠加。

  1. 块级格式化上下文不会重叠浮动元素

根据规定,一个块级格式化上下文的边框不能和它里面的元素的外边距重叠。这就意味着浏览器将会给块级格式化上下文创建隐式的外边距来阻止它和浮动元素的外边距叠加。由于这个原因,当给一个挨着浮动的块级格式化上下文添加负的外边距时将会不起作用(Webkit和IE6在这点上有一个问题——可以看这个测试用例)。

  1. 块级格式化上下文通常可以包含浮动

详见: W3C CSS2.1 - 10.6.7 'Auto' heights for block formatting context roots

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

至此,您或许明白了为什么 overflow:hidden或者auto可以闭合浮动了,真是因为父元素创建了新的BFC。对于张鑫旭在对《overflow与zoom”清除浮动”的一些认识 》一文中对于用包裹来解释闭合浮动的原理,我觉得是不够严谨的,而且没有依据。并且说道“Firefox等浏览器并没有haslayout的概念”,那么现代浏览器是有BFC的,从表现上来说,hasLayout 可以等同于 BFC。

IE6-7的显示引擎使用的是一个称为布局(layout)的内部概念,由于这个显示引擎自身存在很多的缺陷,直接导致了IE6-7的很多显示bug。当我们说一个元素“得到 layout”,或者说一个元素“拥有 layout” 的时候,我们的意思是指它的微软专有属性 hasLayout http://msdn.microsoft.com/works... 为此被设为了 true 。IE6-7使用布局的概念来控制元素的尺寸和定位,那些拥有布局(have layout)的元素负责本身及其子元素的尺寸设置和定位。如果一个元素的 hasLayout 为false,那么它的尺寸和位置由最近拥有布局的祖先元素控制。

浮动和清除浮动

了解了BFC之后,在简单的回忆一下CSS中的float属性。众所周知,在CSS的布局中,早期采用布局多半是依赖于float属性,但元素浮动之后会造成容器的高度坍塌。为了避免这个现象,有了各式各样的清除浮动的黑魔法。至于浮动和清除浮动的相关知识,欢迎阅读下面的相关文章:

  • CSS的Float之一
  • CSS的Float之二
  • float深入剖析
  • float是如何工作的
  • Clear Float

二、闭合浮动的原理

BFC的理解


  • BFC就是对B(Block)的FC(Formatting Contexts),简单说就是块级元素的排列规则,同样的还有IFC,即对行内元素的排列规则。
  • Formatting Contexts,是W3C CSS2.1引入的概念,可以理解为页面中的一块渲染区域,并且与外界相隔离,有一套自己的规则,它决定了在这块区域中其子元素ru和定位吗,排列以及和其他元素的关系和相互作用。
  • CSS2.1中增加了BFC和IFC,CSS3中还增加了GFC和FFC。
  • Box是CSS布局的基本单位,也就是说,一个页面实际上是由很多Box组合而成的。对Box声明不同的display类型,则生成不同类型的Box。不同类型的Box会参与不同的Formatting Contexts(一个决定如何渲染文档额的容器),因此Box内的元素会以不同的方式渲染。

触发hasLayout的条件:

  1. position: absolute
  2. float: left|right
  3. display: inline-block
  4. width: 除 “auto” 外的任意值
  5. height: 除 “auto” 外的任意值 (例如很多人闭合浮动会用到 height: 1% )
  6. zoom: 除 “normal” 外的任意值
  7. 在 IE7 中,overflow 也变成了一个 layout 触发器:
    overflow: hidden|scroll|auto ( 这个属性在IE之前版本中没有触发 layout 的功能。 )
  8. overflow-x|-y: hidden|scroll|auto (CSS3 盒模型中的属性,尚未得到浏览器的广泛支持。他们在之前IE版本中同样没有触发 layout 的功能)

hasLayout更详细的解释请参见 old9翻译的 大名鼎鼎的 《On having layout》一文(英文原文:http://www.satzansatz.de/cssd/onhavinglayout.htm),由于old9博客被墙,中文版地址:

IE8使用了全新的渲染引擎,删除了 hasLayout 原本的功能.aspx#浮动),因此彻底杜绝了很多深恶痛绝的 bug,但 IE8~IE11 通过「document.documentElement.currentStyle.hasLayout」依然可以获得 hasLayout 的标志,我写了一个测试 Demo(IE8 中 zoom:1 返回 false),更详细的请看《IE8 haslayout = true》

综上所述:

  • 在支持BFC的浏览器(IE8 ,firefox,chrome,safari)通过创建新的BFC闭合浮动;
  • 在不支持 BFC的浏览器 (IE6-7),通过触发 hasLayout 闭合浮动。

flow-root

了解了BFC、浮动和清除浮动之后,咱们回到今天要聊的flow-root。W3C规范中是这样描述flow-root的:

The element generates a block container box, and lays out its contents using flow layout. It always establishes a new block formatting context for its contents.

简单地说,元素容器会生成一个块盒子,并且块盒子里的内容是使用流布局。它总是为它建立一个新的块格式化上下文内容。如果你对CSS中浮动有所了解之后,你不难发现,容器里的元素浮动之后,会造成容器的坍塌现象之类的。

图片 1

通过clearfix之后,能让其变得正常:

图片 2

看到这里,或许你知道flow-root的特性是什么了。其实正如你所想的一样:flow-root是最新一种创建BFC的属性。正因为如此,大多数人都认为flow-root就是一个简单的clearfix黑魔法,也有很多人说他是最新清除浮动的最简易方案。但这个特性其实真的很有实用性。

  常用的清除浮动方法有许多,可分为两类

  那么其中的原理是什么呢,在这之前需要先了解一下hasLayout 和 Block formatting contexts。

所谓Block formatting contexts是指块级格式化上下文,简称BFC。

那么如何触发BFC呢?

  • float 除了none以外的值   
  • overflow 除了visible 以外的值(hidden,auto,scroll )   
  • display (table-cell,table-caption,inline-block)   
  • position(absolute,fixed)   
  • fieldset元素

需要注意的是,display:table 本身并不会创建BFC,但是它会产生匿名框(anonymous boxes),而匿名框中的display:table-cell可以创建新的BFC,换句话说,触发块级格式化上下文的是匿名框,而不是 display:table。所以通过display:table和display:table-cell创建的BFC效果是不一样的。

 fieldset 元素在www.w3.org里目前没有任何有关这个触发行为的信息,直到HTML5标准里才出现。有些浏览器bugs(Webkit,Mozilla)提到过这个触发行为,但是没有任何官方声明。实际上,即使fieldset在大多数的浏览器上都能创建新的块级格式化上下文,开发者也不应该把这当做是理所当然的。CSS 2.1没有定义哪种属性适用于表单控件,也没有定义如何使用CSS来给它们添加样式。用户代理可能会给这些属性应用CSS属性,建议开发者们把这种支持当做实验性质的,更高版本的CSS可能会进一步规范这个。

 

BFC的特性:

BFC的特性


一个元素,声明了某种规则(后面会讲触发规则),触发了BFC后,便拥有了BFC特性,那什么是BFC特性呢?特性就是前一段所说的,其为拥有一套独立的渲染规则的区域,并且这块区域不受外界的影响,是相对隔离的区域(也有的地方说容器)。区域中的子元素不会在布局上影响外面的元素,反之亦然。同时,BFC仍然属于文档中的普通流。

  1. 内部的box会在垂直方向上一个接一个的排列;
  2. Box垂直方向上的距离由外边距决定。当两个相邻的容器在同一个BFC中时,他们的垂直方向会发生外边距叠加,换句话说,只要把两个元素分隔在不同的BFC,便可以消除影响,从而解决外边距合并问题;;
  3. 每个元素的左外边距与包含块的左边界相接触(从左到右),即使浮动元素也是如此。(这说明BFC中的子元素不会超出它的包含块,而position为absolute的元素可以超出它的包含块边界);
  4. BFC的区域不会与float box所占的区域重叠;
  5. 计算BFC的高度时,浮动子元素也参与计算;(顺带达到了撑开父容器,清除浮动的目的)

闭合浮动方法——精益求精

上面已经列举了7种闭合浮动的方法,通过第三节分析的原理,我们发现其实更多的:display:table-cell,display:inline-block等只要触发了BFC的属性值都可以闭合浮动。从各个方面比较,after伪元素闭合浮动无疑是相对比较好的解决方案了,下面详细说说该方法。

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

.clearfix { *zoom:1; } 
  1. display:block 使生成的元素以块级元素显示,占满剩余空间;
  2. height:0 避免生成内容破坏原有布局的高度。
  3. visibility:hidden 使生成的内容不可见,并允许可能被生成内容盖住的内容可以进行点击和交互;
  4. 通过 content:"."生成内容作为最后一个元素,至于content里面是点还是其他都是可以的,例如oocss里面就有经典的content:"XXXXXXXXX",有些版本可能content 里面内容为空,一丝冰凉是不推荐这样做的,firefox直到7.0 content:”" 仍然会产生额外的空隙;
    5)zoom:1 触发IE hasLayout。

通过分析发现,除了clear:both用来闭合浮动的,其他代码无非都是为了隐藏掉content生成的内容,这也就是其他版本的闭合浮动为什么会有font-size:0,line-height:0。

使用display:flow-root

今天开始你可以使用display:flow-root。这周Firefox 53和Chrome 58两大主流浏览器在这周都发布相关消息:支持flow-root属性值。

来看一个简单的示例,比如我们一个这样的结构:

浮动元素

浮动元素

我们的CSS是这样的:

.floatElement{ float: left; /*或者right*/ }

1
2
3
.floatElement{
    float: left; /*或者right*/
}

如果仅这样操作,都会造成容器wrapper的高度塌陷。以前我们都是通过clearfix的方案(最常用的吧)来解决:

.wrapper::after { content:''; display: table; clear: both }

1
2
3
4
5
.wrapper::after {
    content:'';
    display: table;
    clear: both
}

上面的解决方案都是老的,其实今天我们可以在.wrapper容器上这样使用就可以达到类似clearfix的效果:

.wrapper{ display: flow-root; }

1
2
3
.wrapper{
    display: flow-root;
}

虽然主流浏览器Firefox 53 Chrome 58 Opera 45 都支持flow-root属性(有关于浏览器对该属性的兼容性,可以通过Caniuse.com来查询)。但实际当中,我们必竟有很多业务需求是需要兼容一些低版本的。对于一位CSS的极度爱好者,总是喜欢在项目中不断的尝试使用一些新特性。为了更好对flow-root做降级处理,我们可以通过CSS的条件属性@supports()来做相应的处理。比如上面的代码我们可以这样使用:

.floatElement{ float: left; /*或者right*/ } .wrapper::after { content:''; display: table; clear: both } @supports(display:flow-root){ .wrapper{ display: flow-root; } .wrapper::after{ content:none; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.floatElement{
    float: left; /*或者right*/
}
.wrapper::after {
    content:'';
   display: table;
   clear: both
}
@supports(display:flow-root){
    .wrapper{
        display: flow-root;
    }
    .wrapper::after{
        content:none;
    }
}

当然你还可以把这样使用:

.floatElement{ float: left; /*或者right*/ } @supports not (display:flow-root) { .wrapper::after { content: ''; display: table; clear:both; } }

1
2
3
4
5
6
7
8
9
10
.floatElement{
    float: left; /*或者right*/
}
@supports not (display:flow-root) {
    .wrapper::after {
        content: '';
        display: table;
        clear:both;
    }
}

是不是很意思呀。我们来看一个@Rachel Andrew在Codepen上面写的一个示例:

这里使用到了CSS的@supports(),如果你从未接触过,建议你点击这里进行阅读。

1)块级格式化上下文会阻止外边距叠加

当两个相邻的块框在同一个块级格式化上下文中时,它们之间垂直方向的外边距会发生叠加。换句话说,如果这两个相邻的块框不属于同一个块级格式化上下文,那么它们的外边距就不会叠加。

如何触发BFC


只要父容器上声明以下任一属性即可触发 BFC:

  • float 除了none以外的值
  • overflow除了visible以外的值(hidden,auto,scroll )
  • display (table-cell,table-caption,inline-block,flex,inline-flex)
  • position(absolute,fixed)
  • fieldset元素(实验性质)
  • 根元素

以上这些规则,均可以触发BFC,具体的选用要取决于场景,不同的属性会带来不同的作用效果;

精益求精方案一:

相对于空标签闭合浮动的方法代码似乎还是有些冗余,通过查询发现Unicode字符里有一个“零宽度空格”,也就是U 200B ,这个字符本身是不可见的,所以我们完全可以省略掉 visibility:hidden了

.clearfix:after {
      content:"200B";
      display:block; 
      height:0; 
      clear:both; } 

.clearfix { *zoom:1; }. 

总结

这篇文章简单的介绍了CSS中的一个新属性flow-root,简单的讲他是最新一种BFC,也是最新的浮除浮动的方案。虽然目前仅几个最新浏览器支持,但完全可以通过@supports()属性做完美降级处理。

2 赞 2 收藏 评论

图片 3

2)块级格式化上下文不会重叠浮动元素

根据规定,一个块级格式化上下文的边框不能和它里面的元素的外边距重叠。这就意味着浏览器将会给块级格式化上下文创建隐式的外边距来阻止它和浮动元 素的外边距叠加。由于这个原因,当给一个挨着浮动的块级格式化上下文添加负的外边距时将会不起作用(Webkit和IE6在这点上有一个问题——可以看这 个测试用例)。 

BFC的应用


  • 解决外边距叠加,方法:使父容器添加触发BFC的元素;
  • 清除浮动:方法:利用计算BFC高度时,浮动元素也会参与计算的原理,所以为了闭合浮动,我们要对父容器触发BFC;
  • 用于布局:利用BFC不会与float box重叠的原理及元素的左/右外边距会触碰到包含块的边沿原理,创建两栏/三栏布局(左右浮动且定宽,中间创建BFC);

精益求精方案二:

由 Nicolas Gallagher 大湿提出来的,原文:A new micro clearfix hack,该方法也不存在firefox中空隙的问题。

/* For modern browsers */ 

.cf:before,.cf:after { 

content:""; 

display:table; 

} 

.cf:after { clear:both; }/* For IE 6/7 (trigger hasLayout) */ 

.cf { zoom:1; } 

需要注意的是:

上面的方法用到了 :before 伪元素,很多人对这个有些迷惑,到底我什么时候需要用 before 呢?为什么方案一没有呢?其实它是用来处理 margin 边距重叠的,由于内部元素 float 创建了BFC,导致内部元素的margin-top和 上一个盒子的 margin-bottom 发生叠加。如果这不是你所希望的,那么就可以加上 before,如果只是单纯的闭合浮动,after 就够了!并不是如同大漠《Clear Float》一文所说的:但只使用 clearfix:after 时在跨浏览器兼容问题会存在一个垂直边距叠加的bug,这不是 Bug,是 BFC 应该有的特性。

请看优雅的Demo

进一步了解请看: 《clearfix改良及overflow:hidden详解【译】》

在实际开发中,改进方案一由于存在Unicode字符不适合内嵌CSS的GB2312编码的页面,使用方案7完全可以解决我们的需求了,改进方案二等待大家的进一步实践。方案3、4通过overflow闭合浮动,实际上已经创建了新的 块级格式化上下文,这将导致其布局和相对于浮动的行为等发生一系列的变化,闭合浮动只不过是一系列变化中的一个作用而已。

所以为了闭合浮动去改变全局特性,这是不明智的,带来的风险就是一系列的 Bug,比如 Firefox 早期版本产生 focus,截断绝对定位的层等等。始终要明白,如果单单只是需要闭合浮动,overflow就不要使用,而不是某些文章所说的“慎用”。

来自 <http://www.cnblogs.com/lhb25/p/story-of-clear-float.html>

做一个清除浮动的类名

.group:before, .group:after {   
content: "";   
display: table; } 
.group:after {   
clear: both; } 
.group {   *zoom: 1; }

http://www.zhangxinxu.com/wordpress/2015/02/css-deep-understand-flow-bfc-column-two-auto-layout

BFC元素家族与自适应布局面面观 理论上,任何BFC元素和浮动搞基的时候,都可以实现自动填充的自适应布局。

但是,由于绝大多数的触发BFC的属性自身有一些古怪的特性,所以,实际操作的时候,能兼顾流体特性和BFC特性来实现无敌自适应布局的属性并不多。下面我们牵驴遛马一个一个瞅瞅(类似行为仅出1个代表示意,你懂的,如float:left/right):
float:left 浮动元素本身BFC化,然而浮动元素有破坏性和包裹性,失去了元素本身的流体自适应性,因此,无法用来实现自动填满容器的自适应布局。不过,其因兼容性还算良好,与堆积木这种现实认知匹配,上手简单,因此在旧时代被大肆使用,也就是常说的“浮动布局”,也算阴差阳错开创了自己的一套布局。

position:absolute 这个脱离文档流有些严重,过于清高,不跟普通小伙伴玩耍,我就不说什么了……

overflow:hidden 这个超棒的哦!不像浮动和绝对定位,玩得有点过。也就是溢出剪裁什么的,本身还是个很普通的元素。因此,块状元素的流体特性保存相当完好,附上BFC的独立区域特性,可谓如虎添翼,宇宙无敌!哈无诶瓦(However), 就跟清除浮动:

.clearfix { overflow: hidden; _zoom: 1; }

一样。由于很多场景我们是不能overflow:hidden的,因此,无法作为一个通用CSS类整站大规模使用。因此,float overflow的自适应布局,我们可以在局部(你确定不会有什么被剪裁的情况下)很happy地使用。

display:inline-block CSS届最伟大的声明之一,但是,在这里,就有些捉襟见肘了。display:inline-block会让元素尺寸包裹收缩,完全就不是我们想要的block水平的流动特性。唉,只能是一声叹气一枪毙掉的命!然而,峰回路转,世事难料。大家应该知道,IE6/IE7浏览器下,block水平的元素设置display:inline-block元素还是block水平,也就是还是会自适应容器的可用宽度显示。于是,我们就阴差阳错得到一个比overflow:hidden更牛逼的声明,即BFC特性加身,又流体特性保留。

.float-left { float: left; } .bfc-content { display: inline-block; }

当然,*zoom: 1也是类似效果,不过只适用于低级的IE浏览器,如IE7~

display:table-cell 让元素表现得像单元格一样,IE8 以上浏览器才支持。跟display:inline-block一样,会跟随内部元素的宽度显示,看样子也是不合适的命。但是,单元格有个非常神奇的特性,就是你宽度值设置地再大,大到西伯利亚,实际宽度也不会超过表格容器的宽度。

因此,如果我们把display:table-cell这个BFC元素宽度设置很大,比方说3000像素。那其实就跟block水平元素自动适应容器空间效果一模一样了。除非你的容器宽度超过3000像素,实际上,一般web页面不会有3000像素宽的模块的。所以,要是你实在不放心,设个9999像素值好了!

.float-left { float: left; } .bfc-content { display: table-cell; width: 9999px; }

看上去,好像还不错。但是,还是有两点制约,一是IE8 以上浏览器兼容,有些苦逼的团队还要管IE6;二是应付连续英文字符换行有些吃力(可以嵌套table-layout:fixed解决)。但是,总体来看,适用的场景要比overflow:hidden广博很多。

display:table-row 对width无感,无法自适应剩余容器空间。

display:table-caption 一无是处……还有其他声明也都是一无是处,我就不全部展开了……

总结:我们对BFC声明家族大致过了一遍,能担任自适应布局重任的也就是:
overflow:auto/hidden IE7

display:inline-block IE6/IE7

display:table-cell IE8

由于overflow有剪裁和出现滚动条等隐患,不适合作为整站通用类,于是,最后,类似清除浮动的通用类语句:

.clearfix { *zoom: 1; } .clearfix:after { content: ''; display: table; clear: both; }

两栏或多栏自适应布局的通用类语句是(block水平标签,需配合浮动):

.cell { display: table-cell; width: 9999px; *display: inline-block; *width: auto; }

这就是zxx.lib.cssCSS样式库中.cell的由来!

当然,由于和浮动元素合作,清除浮动还是要的,于是,就有了.fix .l/.r .cell的无敌组合,可以多栏,也可以无限嵌套。

如果是局部,且确认安全;或有连续英文字符换行的隐患,你也可以使用.fix .l/.r .ovh的无敌组合,可以多栏,也可以无限嵌套。

3)块级格式化上下文通常可以包含浮动

详见: W3C CSS2.1 - 10.6.7 'Auto' heights for block formatting context roots    

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

至此,您或许明白了为什么 overflow:hidden或者auto可以闭合浮动了,真是因为父元素创建了新的BFC。对于张鑫旭在对《overflow与zoom”清除浮动”的一些认识 》一文中对于用包裹来解释闭合浮动的原理,我觉得是不够严谨的,而且没有依据。并且说道“Firefox等浏览器并没有haslayout的概念”,那么现代浏览器是有BFC的,从表现上来说,hasLayout 可以等同于 BFC。

IE6-7的显示引擎使用的是一个称为布局(layout)的内部概念,由于这个显示引擎自身存在很多的缺陷,直接导致了IE6-7的很多显示 bug。当我们说一个元素“得到 layout”,或者说一个元素“拥有 layout” 的时候,我们的意思是指它的微软专有属性 hasLayout  ... rties/haslayout.asp 为此被设为了 true 。IE6-7使用布局的概念来控制元素的尺寸和定位,那些拥有布局(have layout)的元素负责本身及其子元素的尺寸设置和定位。如果一个元素的 hasLayout 为false,那么它的尺寸和位置由最近拥有布局的祖先元素控制。

触发hasLayout的条件:

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

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

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

hasLayout更详细的解释请参见 old9翻译的 大名鼎鼎的 《On having layout》一文(英文原文:

IE8使用了全新的显示引擎,据称不使用 hasLayout属性了,因此解决了很多深恶痛绝的bug。

父容器使用overfolow: auto | hidden撑开高度的原理


初次看到overflow:hidden可以解决外边距叠加,清除浮动时,我是很困惑其原理的。直到后面,我尝试理解了BFC,知道其会触发BFC特性,生成一个新的渲染区域,有自己的规则,与外界隔离,也就是不受其他BFC影响了。

但回过头想,我们看下MDN对overflow属的描述:

The overflow CSS property is shorthand for the overflow-x and overflow-y properties, and specifies what to do when content is too large to fit in its block formatting context.

也就是说,overflow属性是用来处理当内容过于长以至于溢出块级容器时,CSS对文本的处理方式;overflow: hidden则是溢出的内容会被裁剪,且不可见。

可以这样理解,overflow:hidden是为了触发包含块计算内容高度,不计算高度overflow怎么裁剪多余部分并隐藏呢?

那怎么计算高度呢?声明了overflow:hidden后需要根据内容的高度来裁剪,浮动元素脱离了文档流,如果未申明高度或高度为auto,那么overflow的高度计算就无从算起,所以要将浮动元素的高度也计算在内,overflow才会起作用,由此,顺带达成了清除浮动的目标;

综上所述:

总结

很多人第一次接触BFC时经常有一个疑问,BFC概念太多了,资料越多往往更难理解。其实,对于BFC我们只需要知道使用一定的CSS声明可以触发BFC,浏览器对生成的BFC有一系列的渲染规则,利用这些渲染规则我们可以达到一定的布局效果,为了达到特定的布局效果我们让元素生成BFC。

我们要记住BFC是页面元素里一个独立存在作用块,它不影响它外面的布局,外面的元素也不会影响到BFC里面的布局,有时候对于页面一些异常效果我们往BFC的思路想想可能会得到解决。

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

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

三、闭合浮动方法——精益求精

上面已经列举了7种闭合浮动(第七种即:after伪元素)的方法,通过第三节分析的原理,我们发现其实更多的:display:table- cell,display:inline-block等只要触发了BFC的属性值都可以闭合浮动。从各个方面比较,after伪元素闭合浮动无疑是相对比 较好的解决方案了,下面详细说说该方法。

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

.clearfix { *zoom:1; }

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

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

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

4)通过 content:"."生成内容作为最后一个元素,至于content里面是点还是其他都是可以的,例如oocss里面就有经典的 content:"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",有些版本可能content 里面内容为空,一丝冰凉是不推荐这样做的,firefox直到7.0 content:”" 仍然会产生额外的空隙;

5)zoom:1 触发IE hasLayout。

通过分析发现,除了clear:both用来清除浮动的,其他代码无非都是为了隐藏掉content生成的内容,这也就是其他版本的闭合浮动为什么会有font-size:0,line-height:0。

 

精益求精方案一:

相对于空标签闭合浮动的方法代码似乎还是有些冗余,通过查询发现Unicode字符里有一个“零宽度空格”,也就是U 200B ,这个字符本身是不可见的,所以我们完全可以省略掉 visibility:hidden了

.clearfix:after {content:"200B"; display:block; height:0; clear:both; }

.clearfix { *zoom:1; }.

精益求精方案二:

由Nicolas Gallagher 大湿提出来的,原文:A new micro clearfix hack,该方法也不存在firefox中空隙的问题。

/* For modern browsers */

.cf:before,.cf:after {

content:"";

display:table;

}

.cf:after { clear:both; }/* For IE 6/7 (trigger hasLayout) */

.cf { zoom:1; }

 需要注意的是:

上面的方法用到了  :before伪元素,很多人对这个有些迷惑,到底我什么时候需要用before呢?为什么方案一没有呢?其实它是用来处理margin边距重叠的,由于 内部元素 float 创建了BFC,导致内部元素的margin-top和 上一个盒子的margin-bottom 发生叠加。如果这不是你所希望的,那么就可以加上before,如果只是单纯的闭合浮动,after就够了!并不是如同大漠《Clear Float》一文所说的:但只使用clearfix:after时在跨浏览器兼容问题会存在一个垂直边距叠加的bug,这不是bug,是BFC应该有的特性。

图片 4

请看优雅的Demo

进一步了解请看: 《clearfix改良及overflow:hidden详解【译】》

在实际开发中,改进方案一由于存在Unicode字符不适合内嵌CSS的GB2312编码的页面,使用方案7完全可以解决我们的需求了,改进方案二 等待大家的进一步实践。方案3、4通过overflow闭合浮动,实际上已经创建了新的 块级格式化上下文,这将导致其布局和相对于浮动的行为等发生一系列的变化,清除浮动只不过是一系列变化中的一个作用而已。所以为了闭合浮动去改变全局特 性,这是不明智的,带来的风险就是一系列的bug,比如firefox 早期版本产生 focus,截断绝对定位的层等等。始终要明白,如果单单只是需要闭合浮动,overflow就不要使用,而不是某些文章所说的“慎用”。

前前后后花了三天写完了这篇文章。如果觉得本文对您有帮助,您的留言就是对我最大的支持,同时由于精力有限,欢迎指出文中错误与不足,共勉之!

参考资料:

 

  • Page breaks and block-formatting contexts: Allowed page breaks (13.3.3)
  • Clearfix and block formatting contexts: Everything you Know about Clearfix is Wrong
  • Block formating contexts, “hasLayout” – IE Window vs CSS2.1 browsers: simulations.
  • New block formatting contexts next to floats
  • Control Block Formatting Context
  • On having layout, [译文]On having layout  
  • “HasLayout” Overview
  • hasLayout Property
  • IE hasLayout

 

 

转自:

一、清除浮动和闭合浮动 所谓清除浮动,是指显示上正确...

本文由星彩网app下载发布于前端技术,转载请注明出处:CSS不可不知,摘自网摘

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。