金沙棋牌官方平台

当前位置:金沙棋牌 > 金沙棋牌官方平台 > 说说Float那个被埋没的志向,重新认识Box

说说Float那个被埋没的志向,重新认识Box

来源:http://www.logblo.com 作者:金沙棋牌 时间:2019-11-21 10:22

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

图片 1 图片 2

1 赞 3 收藏 评论

感谢

KB011: 浮动(Floats)
KB009: CSS 定位体系概述
CS001: 清理浮动的几种方法以及对应规范说明
CSS float浮动的深入研究、详解及拓展(一)
CSS float浮动的深入研究、详解及拓展(二)

CS001: 清理浮动的几种方法以及对应规范说明
Faking ‘float: center’ with Pseudo Elements
说说标准——CSS核心可视化格式模型(visual formatting model)之十:控制紧接浮动的排列-clear 特性
那些年我们一起清除过的浮动

打赏支持我写出更多好文章,谢谢!

打赏作者

什么是BFC

2016/01/09 · CSS · 2 评论 · BFC

原文出处: 大搜车前端团队博客   

这是我10个月前写的一篇关于BFC的文章,因为接下来要写一篇关于FFC的文章了,然而很多人对BFC都还不了解,所以我先把这篇文章拿出来让大家先了解下BFC。

说到BFC,就会涉及到CSS布局的一些基本概念,然后,首先来讲一下关于块级盒的一些概念:

下面是来自w3.org中的一句话(参考链接:http://www.w3.org/TR/CSS2/visuren.html#block-formatting):%EF%BC%9A)

Block-level elements are those elements of the source document that are formatted visually as blocks (e.g., paragraphs). The following values of the ‘display’ property make an element block-level: ‘block’, ‘list-item’, and ‘table’.

大概的意思是块级元素是那种源文档被格式化为可视块了的元素,然后使这个元素变成块级元素的display属性取值如下: ‘block’, ‘list-item’, 和 ‘table’。

然后还有一段话:

Block-level boxes are boxes that participate in a block formatting context. Each block-level element generates a principal block-level box that contains descendant boxes and generated content and is also the box involved in any positioning scheme

块级盒block-level box是这种参与了块级排版上下文的一种盒子,每个块级元素都生成了一个包含后代盒子和生成的内容的主要块级盒,并且这个盒子参与了任何定位的计算

来自w3c官网的一张图:

图片 3

块级元素会自动生成一个块级盒block-level box,这是块级盒block-level-box的盒模型构成,它表明的是块级盒自身的结构构成。再来看w3.org的这样一段话( 参考:http://www.w3.org/TR/CSS2/box.html):%EF%BC%9A)

content edge or inner edge
The content edge surrounds the rectangle given by the width and height of the box, which often depend on the element’s rendered content. The four content edges define the box’s content box.
padding edge
The padding edge surrounds the box padding. If the padding has 0 width, the padding edge is the same as the content edge. The four padding edges define the box’s padding box.
border edge
The border edge surrounds the box’s border. If the border has 0 width, the border edge is the same as the padding edge. The four border edges define the box’s border box.
margin edge or outer edge
The margin edge surrounds the box margin. If the margin has 0 width, the margin edge is the same as the border edge. The four margin edges define the box’s margin box.

从上面这段话可以看出,margin、border、padding、content分别定义了元素四种边,然后每种类型的边的四条边定义了一个盒子,分别是content box、padding box、border box、margin box,而决定块盒在包含块中与相邻块盒的垂直间距的便是margin-box,这个margin-box是始终存在的,即使它的margin为0,试看下面的代码:

XHTML

<div style="width: 400px;height: 400px; background:#ff4400;"></div>

1
<div style="width: 400px;height: 400px; background:#ff4400;"></div>

生成了一个块级的元素,同时元素也生成了一个块级盒:

图片 4

此时我没有为这个div设置margin值,但是这个div还是有一个默认为0的margin的,试看下面的浏览器生成的computed style:

图片 5

可以看到div默认的margin为0,再看看w3.org的相关文档(参考:http://www.w3.org/TR/WD-CSS2/visudet.html):%EF%BC%9A)

图片 6

上面说了元素的四个margin的默认值都是0(见红色部分),然后应用对象是所有的元素(见蓝色部分),所有元素当然包括块级元素,因此所有的块级盒子无论怎样都会有一个margin-box,在BFC中,margin-box会与其相邻的margin-box的对边相折叠(关于BFC的margin折叠这里先不讨论)。margin-box是参与块级盒在上下文中的布局的,但是参与BFC布局的盒子却是块级盒block-level box,并且还有一点需要明确的是参与布局的是盒子而不是元素本身。下面这张图是我自己理解的块级盒block-level box的构成:

图片 7

那么block-level box在页面中是怎样布局的呢。

我们通常的描述是这样的:

普通流中的块元素独占一行,然后从上往下一个接一个的排布,相邻元素间会有外边距折叠

确实是这样(NOTE:这个说法也非绝对严谨,试看DEMO:,那为什么会这样呢,原因就是因为BFC的存在。试看下面的关于BFC的官方文档描述(参考:http://www.w3.org/TR/CSS21/visuren.html):%EF%BC%9A)

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.

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.

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).

大致意思如下: 第一段:浮动元素、绝对定位元素,不是块级盒的块级包含块(比如inline-block、table-cell、table-capation)和overflow值不为visible的块级盒子为它们的内容建立了一个新的块级排版上下文。

第二段:在一个块级排版上下文中,盒子是从包含块顶部开始,垂直的一个接一个的排列的,相邻两个盒子之间的垂直的间距是被margin属性所决定的,在一个块级排版上下文中相邻的两个块级盒之间的垂直margin是折叠的。参与BFC的布局的只有普通流normal flow中的块级盒,而float、position值不为relativestatic的元素是脱离BFC这一布局环境的,不参与BFC的布局

第三段:在一个块级排版上下文中,每个盒子的左外边是触碰到包含块的左边的(对于从右向左的排版,则相反),即使在有浮动元素参与的情况下也是如此(即使一个盒子的行盒是因为浮动而收缩了的),除非这个盒子新建了一个块级排版上下文(在某些情况下这个盒子自身会因为floats而变窄)。

先不解释第一段所描述的内容,先看第二段和第三段话,然后我们再来看一个很常见的实例:   代码如下:

XHTML

<div style="width: 200px;height: 200px;background: #cccccc;"></div> <div style="width: 200px;height: 200px;background: #333333;"></div> <div style="width: 200px;height: 200px;background: #666666;"></div>

1
2
3
<div style="width: 200px;height: 200px;background: #cccccc;"></div>
<div style="width: 200px;height: 200px;background: #333333;"></div>
<div style="width: 200px;height: 200px;background: #666666;"></div>

结果如下:图片 8

三个块级盒,从上往下排列,看样子是遵循如上面第二段所述的这一条BFC布局规则的:“在一个块级排版上下文中,盒子是从包含块顶部开始,垂直的一个接一个的排列的”,那么这里的盒子要从上往下排列的话,肯定是得要一个包含块containing block和一个块级排版上下文BFC的,:root元素是会在其下创建一个BFC的,那么在这个BFC下的所有块级盒都是会在它的包含块中垂直的一个接一个的排布的。但是元素的包含块是什么呢,试看来自w3.org的一段话(参考:http://www.w3.org/TR/CSS2/visudet.html):%EF%BC%9A)

The position and size of an element’s box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element:

意思是:元素盒子的位置和尺寸往往是根据一个矩形计算出来的,我们称这个矩形为元素的包含块 然后它下面还有一句:

if the element’s position is ‘relative’ or ‘static’, the containing block is formed by the content edge of the nearest block container ancestor box.

意思是:如果这个元素的position值是relative或static,这个元素的包含块是由离其最近的块级的祖先盒子的内容的边content-edge构成的。就是离其最近的块级祖先盒子的content-box。

搞清了包含块containing block的概念,再来看看这个实例中的3个div的包含块,很显然是其父级元素body,同时还在canvas所设立的BFC下,按照“在一个块级排版上下文中,盒子是从包含块顶部开始,垂直的一个接一个的排列的”的这个定义,我们已经确定了,这里的div是会垂直的一个接一个的排列的,但是你要注意到,第二段话只是定义了垂直方向的排布规则,还没说水平方向的,那么水平方向的又如何呢,试看第三段话的前两句:“在一个块级排版上下文中,每个盒子的左外边是触碰到包含块的左边的(对于从右向左的排版,则相反)”,而在这里,我尚未为其定义从右向左的排版(对于从右向左的排版,参考:,所以这个div的左外边是会触碰到包含块body的左边的。

本文只讨论什么是BFC,因此上面那段话中的某些原文就不一 一解释了。

再来看上面那段话第二段中的一句话:“相邻两个盒子之间的垂直的间距是被margin属性所决定的,在一个块级排版上下文中相邻的两个块级盒之间的垂直margin是折叠的”,这是参与BFC布局的块级盒的又一特性,试看以下实例:

代码:

XHTML

<div style="width: 200px;height: 200px;background: #cccccc;margin-bottom: 30px;"></div> <div style="width: 200px;height: 200px;background: #333333;margin-top: 30px;margin-bottom:30px;"> </div> <div style="width: 200px;height: 200px;background: #666666;margin-top: 50px;"></div>

1
2
3
<div style="width: 200px;height: 200px;background: #cccccc;margin-bottom: 30px;"></div>
<div style="width: 200px;height: 200px;background: #333333;margin-top: 30px;margin-bottom:30px;">   </div>
<div style="width: 200px;height: 200px;background: #666666;margin-top: 50px;"></div>

如图:

图片 9

可以看到上下两个div的margin折叠了,第一个div的margin-bottom和第二个div的margin-top折叠为了30px,第二个div的margin-bottom和第三个div的margin-top折叠为了50px,而这个折叠本质是块级盒block-level box下的margin-box的折叠,后面会讲到如果再到这几个div的外面一层再包裹一个拥有BFC的元素的话,他们之间的margin便不会折叠了,因为BFC里面的盒子和其外面的盒子间是不会有任何影响的,你可能会疑惑那这里的三个div不是也在:root所设立的BFC下吗,那为什么还会折叠,原因很简单,就是因为你那个BFC在:root那里去了,BFC相当于一堵墙,你这个墙在这里应该在每个div的外面才会起到隔离这几个div的作用啊,而:root下的那个BFC则是隔离的:root下的直接子元素了。关于margin折叠方面的还有很多细节,可以参考官方文档:

至此,我们就搞清楚普通流中的块级盒的一些基本特性的来龙去脉了。

上面说的都是:root下的BFC。那么,假设你在不知道比如float的这些特性能用于创建BFC的时候,你会不会很好奇的去想:root下的盒子会不会也有可以用于创建BFC的方法与对应的盒子呢?上下文套上下文可是一件很令人感到愉悦的事情,因为我可以把那个能创建BFC的盒子当作那个:root,而这个创建了BFC的盒子则是一个独立的容器,里面的参与BFC的块级盒不会影响到盒子外面的盒子,外面的盒子也不会影响到里面参与了BFC的块级盒。试看以下demo:  :; :;代码如下:

XHTML

<div style="overflow: auto;width: 100%;"> <div style="float: left;width: 100%;"> <div style="margin-bottom: 30px;width: 100px;height: 100px;background-color: #cccccc;"></div> </div> <div style="float: left;width: 100%;"> <div style="margin-top: 50px;width: 100px;height: 100px;background-color: #333333;"></div> </div> </div>

1
2
3
4
5
6
7
8
<div style="overflow: auto;width: 100%;">
    <div style="float: left;width: 100%;">
        <div style="margin-bottom: 30px;width: 100px;height: 100px;background-color: #cccccc;"></div>
    </div>
    <div style="float: left;width: 100%;">
        <div style="margin-top: 50px;width: 100px;height: 100px;background-color: #333333;"></div>
    </div>
</div>

 :; :;结果如下:

图片 10

可以看到,上面示例中的上面灰色div和下面黑色div的margin并没有重叠,这是因为那两个float的父盒子在为它下面的盒子创建了一个BFC,从而将float盒子里面的子盒子给隔离了起来,因此也就不会margin折叠了,这只是创建BFC的一个方法,其它的还有overflow:hidden等,而在这个BFC下的盒子都是遵循BFC的布局规则的。

然后我们来从盒模型的角度来理解下,BFC是如何将其下的盒子与外界隔离起来的,首先,最基本的盒子构成我们上面已经说过了,见上面的描述block-level box的构成的那张图:

然后,当块级盒block-level box外层没有BFC作保护,有margin折叠时,是这样的:

图片 11

而当块级盒block-level box外层有BFC作保护时(比如给下图灰色边框线盒子一个float:left),则是这样的:

图片 12

同时BFC下的盒子是按照BFC的规则从上往下一个接一个的排列,并且存在外边距折叠的,你可以通过在这层BFC下再去嵌套BFC来阻止下面盒子的外边距折叠

图片 13

最后,我们通过一张图来了解一个页面中的BFC的构成(有红色虚线的代表的是拥有BFC的元素):

图片 14

BFC描述的是页面中的,严格来说是页面的:root下的一个布局上下文,它下面的盒子遵循BFC中的布局规则,它是描述的是块级盒的布局规则,那么行盒,行级盒等盒子又是遵循什么样的布局规则的呢?这里就不细讲了,可以看看winter老师的两张图,有助于对BFC的理解,也有助于对CSS布局的理解:

图片 15

图片 16

最后要说的就是,本文只对BFC作了一个初步的介绍,如果要了解更多的细节,可以参考以下相关标准:



1 赞 15 收藏 2 评论

图片 17

绝对定位(Absolute positioning)

  • 绝对定位方案,盒从常规流中被移除,不影响常规流的布局;
  • 它的定位相对于它的包含块,相关CSS属性:topbottomleftright
  • 如果元素的属性positionabsolutefixed,它是绝对定位元素;
  • 对于position: absolute,元素定位将相对于最近的一个relativefixedabsolute的父元素,如果没有则相对于body

关于作者:^-^肥仔John

图片 18

偏前端的临栈工程师 个人主页 · 我的文章 · 5 ·    

图片 19

脚踩block-level box

相对line box,block-level box就显得不屈不挠了。width:auto时其宽度始终保持占满containing block宽度的态度。但位于同一个stacking context中的浮动定位的盒子虽然和常规流中的盒子拥有相同的z-index(都是auto),但浮动定位的盒子拥有额外的优先级,导致它总位于常规流中的盒子之上。(关于分层显示的内容可参考《CSS魔法堂:你真的理解z-index吗?》)
图片 20

XHTML

<div style="float:left;border:solid 1px red;width:100px;height:50px;">float:left</div> <div style="background:#06f;width:200px;height:100px;"></div>

1
2
<div style="float:left;border:solid 1px red;width:100px;height:50px;">float:left</div>
<div style="background:#06f;width:200px;height:100px;"></div>

实例二

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

XHTML

.BFC{ overflow: hidden; } <div class='box BFC'> <div class='left'> </div> <div class='right'> </div> </div>

1
2
3
4
5
6
7
8
.BFC{
overflow: hidden;
}
 
<div class='box BFC'>
<div class='left'> </div>
<div class='right'> </div>
</div>

图片 21

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

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

CSS魔法堂:重新认识Box Model、IFC、BFC和Collapsing margins

2016/05/10 · CSS · BFC, Box Model, Collapsing margins, IFC

本文作者: 伯乐在线 - ^-^肥仔John 。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

前言
盒子模型作为CSS基础中的基础,曾一度以为掌握了IE和W3C标准下的块级盒子模型即可,但近日在学习行级盒子模型时发现原来当初是如此幼稚可笑。本文尝试全面叙述块级、行级盒子模型的特性。作为近日学习的记录。

何为盒子模型?
盒子模型到底何方神圣居然可以作为CSS的基础?闻名不如见面,上图了喂!
图片 22
再来张切面图吧!
图片 23
下面我们以 <div></div> 为栗子。 <div></div> 标签被浏览器解析后会生成div元素并添加到document tree中,但CSS作用的对象并不是document tree,而是根据document tree生成的render tree,而盒子模型就是render tree的节点。
* 注意:
* 1. CSS作用的是盒子(Box), 而不是元素(Element);
* 2. JS无法直接操作盒子。

盒子模型的结构
由于块级盒子在验证效果时干扰信息更少,便于理解盒子模型,因此下面将以块级盒子模型来讲解。
注意: 行级盒子模型与块级盒子模型结构一致,只是行级盒子在此基础上有自身特性而已。
从上面两幅图说明盒子模型其实就是由以下4个盒子组成:

  1. content box:必备,由content area和4条content/inner edge组成;
  2. padding box:可选,由padding和4条padding edge组成。若padding宽度设置为0,则padding edge与content edage重叠;
  3. border box:可选,由border和4条border edge组成。若border宽度设置为0,则border edge与padding edage重叠;
  4. margin box:可选,由margin和4条margin/outer edge组成。若margin宽度设置为0,则margin edge与border edage重叠。
    对于刚接触CSS的同学,经常会将”通过width/height属性设置div元素的宽/高”挂在口边,其实这句话是有误的。
  5. 首先css属性width和height作用于div元素所产生的盒子,而不是元素本身;
  6. 另外盒子模型由4个盒子组成,那width和height到底是作用于哪些盒子呢?
    这里就分为IE盒子模型和标准盒子模型了。
       IE box model    
    IE5.5(怪异模式)采用IE盒子模型,其它将使用W3C标准盒子模型。
    图片 24

JavaScript

width = content-width + padding-width + border-width height = content-height + padding-height + border-height

1
2
width = content-width + padding-width + border-width
height = content-height + padding-height + border-height

  Standard box model  
图片 25

JavaScript

width = content-width height = content-height

1
2
width = content-width
height = content-height

游走于IE box model 和 Standard box model间的通道——box-sizing属性
我们看到存在两种width/height的划分方式,到底哪种才对呢?其实两种都对,具体看如何使用而已。另外IE8开始支持CSS3属性box-sizing,让我们可以自由选择采用哪种盒子:)
box-sizing:content-box/border-box/inherit
content-box——默认值,采用Standard box model
border-box——采用IE box model
inherit——继承父元素属性值
sample:

CSS

Element{ -moz-box-sizing: border-box; // FireFox3.5+ -o-box-sizing: border-box; // Opera9.6(Presto内核) -webkit-box-sizing: border-box; // Safari3.2+ -ms-box-sizing: border-box; // IE8 box-sizing: border-box; // IE9+,Chrome10.0+,Safari5.1+,Opera10.6 }

1
2
3
4
5
6
7
Element{
  -moz-box-sizing: border-box; // FireFox3.5+
  -o-box-sizing: border-box; // Opera9.6(Presto内核)
  -webkit-box-sizing: border-box; // Safari3.2+
  -ms-box-sizing: border-box; // IE8
  box-sizing: border-box; // IE9+,Chrome10.0+,Safari5.1+,Opera10.6
}

行级盒子——怀疑人生de起点:)                  
之前我理解的盒子模型如上所述,当我看到行级盒子的种种现象时,便开始怀疑人生了:(
width/height不起作用。。。

CSS

.defined-wh{ width: 100px; height: 50px; border: solid 1px red; background: yellow; }

1
2
3
4
5
6
7
.defined-wh{
  width: 100px;
  height: 50px;
 
  border: solid 1px red;
  background: yellow;
}

对于block-level box

XHTML

<div class="defined-wh"></div>

1
<div class="defined-wh"></div>

图片 26
对于inline-level box

XHTML

<span class="defined-wh"></span>

1
<span class="defined-wh"></span>

图片 27
行级盒子的宽度怎么会是0呢?高度是有的但不是50px啊,到底什么回事啊?
原因很简单,那就是行级盒子的content box的高/宽根本就不是通过height/width来设置的。
content box/area的高由font-size决定的;
content box/area的宽等于其子行级盒子的外宽度(margin+border+padding+content width)之和。

  行级盒子被挤断了。。。

CSS

.broken{ border: solid 1px red; background: yellow; }

1
2
3
4
.broken{
  border: solid 1px red;
  background: yellow;
}

对于block-level box

XHTML

<div class="broken">一段文字一段文字一段文字一段文字一段文字一段文字</div>

1
<div class="broken">一段文字一段文字一段文字一段文字一段文字一段文字</div>

图片 28
对于inline-level box

XHTML

<span class="broken">一段文字一段文字一段文字一段文字一段文字一段文字</span>

1
<span class="broken">一段文字一段文字一段文字一段文字一段文字一段文字</span>

图片 29
行级盒子被五马分尸了,可怜兮兮的。更可怜的是我理解不了。。。
其实W3C Recommendation有说明的哦!
>The box model for inline elements in bidirectional context
>When the element’s ‘direction’ property is ‘ltr’, the left-most generated box of the first line box in which the element appears has the left margin, left border and left padding, and the right-most generated box of the last line box in which the element appears has the right padding, right border and right margin.
>When the element’s ‘direction’ property is ‘rtl’, the right-most generated box of the first line box in which the element appears has the right padding, right border and right margin, and the left-most generated box of the last line box in which the element appears has the left margin, left border and left padding.
就是说当inline-level box宽度大于父容器宽度时会被拆分成多个inline-level box,
当属性direction为ltr时,margin/border/padding-left将作用于第一个的inline-level box,margin/border/padding-right将作用于最后一个的inline-level box;若属性direction为rtl时,margin/border/padding-right将作用于第一个的inline-level box,margin/border/padding-left将作用于最后一个的inline-level box。
看到了没?行级盒子真的会被分尸的,好残忍哦:|

行级盒子怎么不占空间了?怎么刷存在感啊。。。

CSS

.existed{ margin: 20px; padding: 20px; border: solid 1px red; background: yellow; background-clip: content-box; }

1
2
3
4
5
6
7
.existed{
  margin: 20px;
  padding: 20px;
  border: solid 1px red;
  background: yellow;
  background-clip: content-box;
}

对于block-level box

XHTML

<div>before bababababababa</div> <div class="existed">babababababababababa</div> <div>after bababababababa</div>

1
2
3
<div>before bababababababa</div>
<div class="existed">babababababababababa</div>
<div>after bababababababa</div>

图片 30
对于inline-level box

XHTML

<div>before bababababababa</div> <span class="existed">babababababababababa</span> <div>after bababababababa</div>

1
2
3
<div>before bababababababa</div>
<span class="existed">babababababababababa</span>
<div>after bababababababa</div>

图片 31
看,行级盒子的margin/border/padding-top/bottom怎么均不占空间的?难道行级盒子仅有content box占空间吗?
这里已经涉及到水平和垂直方向排版的范畴了,仅以盒子模型已无法解析理解上述的问题。
(要结合)

在深入解释inline-level box的上述现象前,我们需要补充一下:

  1. 一个元素会对应0~N个box;(当设置display:none;时,则对应0个box)
  2. 根据display属性值,元素会对应不同类型的controlling box(inline/block-level box均是controlling box的子类). 就CSS2而言display:inline|inline-block|inline-table|table-cell|table-column-group的元素对应inline-level box,而display:block|list-item|table|table-caption|table-header-group|table-row|table-row-group|table-footer-group的元素则对应block-level box;
  3. box布局/排版时涉及到定位问题,而CSS中通过positioning scheme来定义,其包含normal flow、floats和absolute positioning三种定位方式.而normal flow包含block formatting、inline formatting和relative positioning,其中BFC为block formatting的上下文,IFC为inline formatting的上下文。

因此大家请注意,前方高能,前方高能!!!

和IFC一起看inline-level box
IFC(Inline Formatting Context),直译为“行内格式化上下文”,这是什么鬼的翻译啊?反正我对于名词一向采用拿来主义,理解名词背后的含义才是硬道理。
我们简单理解为每个盒子都有一个FC特性,不同的FC值代表一组盒子不同的排列方式。有的FC值表示盒子从上到下垂直排列,有的FC值表示盒子从左到右水平排列等等。而IFC则是表示盒子从左到右的水平排列方式,仅此而已(注意:一个盒子仅且仅有一个FC值)。而inline-level box的FC特性值固定为IFC
另外仅处于in-flow的盒子才具有FC特性,也就是positioning scheme必须为Normal flow的盒子才具有FC特性。
除了IFC外,对于inline-level box排版而言还有另一个重要的对象,那就是line box。line box是一个看不见摸不着的边框,但每一行所占的垂直高度其实是指line box的高度,而不是inline-level box的高度。
  line box的特点:

  1. 同一行inline-level box均属于同一个line box;
  2. line box高度的计算方式()
    >The height of each inline-level box in the line box is calculated. For replaced elements, inline-block elements, and inline-table elements, this is the height of their margin box; for inline boxes, this is their ‘line-height’.
    >The inline-level boxes are aligned vertically according to their ‘vertical-align’ property. In case they are aligned ‘top’ or ‘bottom’, they must be aligned so as to minimize the line box height. If such boxes are tall enough, there are multiple solutions and CSS 2.1 does not define the position of the line box’s baseline.
    >The line box height is the distance between the uppermost box top and the lowermost box bottom.

CSS

.parent{ line-height: 1; font-size: 14px; border: solid 1px yellow; } .child{ font-size: 30px; vertical-align: middle; border: solid 1px blue; } .inline-block{ display: inline-block; overflow: hidden; border: solid 1px red; } .other{ border: solid 1px green; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.parent{
  line-height: 1;
  font-size: 14px;
  border: solid 1px yellow;
}
.child{
  font-size: 30px;
  vertical-align: middle;
  border: solid 1px blue;
}
.inline-block{
  display: inline-block;
  overflow: hidden;
  border: solid 1px red;
}
.other{
  border: solid 1px green;
}

XHTML

<span class="parent"> <span class="child"> <span class="inline-block">display:inline-block元素</span> xp子元素的文字 </span> xp父元素的文字 </span> <div class="other">其他元素</div>

1
2
3
4
5
6
7
8
<span class="parent">
  <span class="child">
    <span class="inline-block">display:inline-block元素</span>
    xp子元素的文字
  </span>
  xp父元素的文字
</span>
<div class="other">其他元素</div>

图片 32

  1. 根据规则,span.parent所在行的line box的高度受span.parent、span.child、span.inline-block元素对应的inline-level box”高度”的影响。其中span.parent的”高度”为其line-height实际值,span.child的”高度”为其line-height实际值,而span.inline-block的”高度”为其margin box的高度。由于设置line-height:1,因此span.parent和span.child的content box高度等于line-height实际值;
    2. 根据vertical-align属性垂直对齐,造成各“高度”间并不以上边界或下边界对齐;
  2. span.inline-block红色的上边框(border top)到span.child蓝色的下边框(border bottom)的距离再减去1px即为line box的高度。(line box的下界其实是span.child的content box的下限的,你看”其他元素”的上边框不是和span.child的下边框重叠了吗?如果那是line box的下界,那怎会出现重叠呢)

这里又涉及到另一个属性vertical-align了,由于它十分复杂,还是另开文章来叙述吧!

                      行级盒子小结                          
*就盒子模型而言***

  1. inline-level box与block-level box结构一致;
  2. content box的高度仅能通过属性font-size来设置,content box的宽度则自适应其内容而无法通过属性width设置;
  3. 当inline-level box的宽度大于containing block,且达到内容换行条件时,会将inline-level拆散为多个inline-level box并分布到多行中,然后当属性direction为ltr时,margin/border/padding-left将作用于第一个的inline-level box,margin/border/padding-right将作用于最后一个的inline-level box;若属性direction为rtl时,margin/border/padding-right将作用于第一个的inline-level box,margin/border/padding-left将作用于最后一个的inline-level box。

*垂直排版特性***
inline-level box排版单位不是其本身,而是line box。重点在于line box高度的计算。

  1. 位于该行上的所有in-flow的inline-level box均参与该行line box高度的计算;(注意:是所有inline-level box,而不仅仅是子元素所生成的inline-level box)
  2. replaced elements, inline-block elements, and inline-table elements将以其对应的opaque inline-level box的margin box高度参与line box高度的计算。而其他inline-level box则以line-height的实际值参与line box高度的计算;
  3. 各inline-level box根据vertical-align属性值相对各自的父容器作垂直方向对齐;
  4. 最上方的box的上边界到最下方的下边界则是line box的高度。(表述不够清晰,请参考实例理解)

Collapsing margins                      
大家必定听过或遇过collapsing margins吧,它是in-flow的block-level box排版时的一类现象。说到排版那必须引入另一个FC特性值——BFC(Block Formatting Context)的。
BFC则是表示盒子从上到下的垂直排列方式,仅此而已(注意:一个盒子仅且仅有一个FC值)。而block-level box的FC特性值固定为BFC。
collapsing margins规则
1. 元素自身margin-top/bottom collapsing

XHTML

anonymous block-level box <div class="margins"></div> anonymous block-level box <div class="margins border"></div> anonymous block-level box

1
2
3
4
5
anonymous block-level box
<div class="margins"></div>
anonymous block-level box
<div class="margins border"></div>
anonymous block-level box

CSS

.margins{margin: 50px 0 70px;} .border{border: solid 1px red;}

1
2
.margins{margin: 50px 0 70px;}
.border{border: solid 1px red;}

图片 33
当block-level box高度为0,垂直方向的border和padding为0,并且没有in-flow的子元素。那么它垂直方向的margin将会发生重叠。

2. 父子元素margin-top/top 或 margin-bottom/bottom collapsing

XHTML

anonymous block-level box <div class="parent-margins"> <div class="margins border"></div> anonymous block-level box <div class="margins border"></div> </div> anonymous block-level box <div class="parent-margins border"> <div class="margins border"></div> anonymous block-level box <div class="margins border"></div> </div> anonymous block-level box

1
2
3
4
5
6
7
8
9
10
11
12
13
anonymous block-level box
<div class="parent-margins">
  <div class="margins border"></div>
  anonymous block-level box
  <div class="margins border"></div>
</div>
anonymous block-level box
<div class="parent-margins border">
  <div class="margins border"></div>
  anonymous block-level box
  <div class="margins border"></div>
</div>
anonymous block-level box

CSS

.parent-margins{margin: 25px 0;} .margins{margin: 50px 0 25px;} .border{border: solid 1px red;}

1
2
3
.parent-margins{margin: 25px 0;}
.margins{margin: 50px 0 25px;}
.border{border: solid 1px red;}

图片 34
当父子元素margin-top间或margin-bottom间没有padding、border阻隔时,则会margin会发生重叠。
注意空白字符会造成目标父子元素间的存在anonymous block-level box,导致margin不重叠。

XHTML

anonymous block-level box <div class="parent-margins">  <div class="margins border"></div> anonymous block-level box <div class="margins border"></div> </div> anonymous block-level box

1
2
3
4
5
6
7
anonymous block-level box
<div class="parent-margins">&nbsp;
  <div class="margins border"></div>
  anonymous block-level box
  <div class="margins border"></div>
</div>
anonymous block-level box

图片 35

3. 兄弟元素margin-bottom/top collapsing

XHTML

<div class="margins">former</div> <div class="margins">latter</div>

1
2
<div class="margins">former</div>
<div class="margins">latter</div>

CSS

.margins{margin: 50px 0 25px;}

1
.margins{margin: 50px 0 25px;}

两个相邻的in-flow block-level box的上下margin将发生重叠。

*上述为默认情况下block-level box(即display:block,其它为默认值时)的margin重叠规则***
那非默认情况下呢?相比非默认情况下的margin重叠规则,我们更关心是什么时候不会产生重叠。这时又引入了另一个概念——生成新BFC。也就是block-level box A与block-level box B的FC特性值BFC可能是不同的。
当两个相邻box的FC值不为同一个BFC时,它们的margin绝对不会重叠。
那么剩下的问题就是,到底何时会产生新的BFC?哪些block-level box会采用新的BFC?默认BFC又是谁生成的呢?
其实根元素(html)会生成默认BFC供其子孙block-level box使用。
采用floats或absolute positioning作为positioning scheme时,或display:inline-block/table-cell/table-caption/flex/inline-flex或overflow属性值不为visible时,则会产生新的BFC;而新的BFC将作为子孙block-level box的FC属性值。
注意:
    1. 产生新BFC的盒子不会与子盒子发生margin重叠;
    2. display:inline-block的盒子不与 兄弟 和 父 盒子发生margin重叠,是因为display:inline-block的盒子的FC特性值为IFC,还记得line box吗?没有margin重叠是自然不过的事了;
    3. positioning scheme为floats的盒子不与floated的兄弟盒子发生margin重叠,也不会与前一个in-flow的兄弟盒子发生margin重叠。(注意:与父盒子也不会发生margin重叠)

XHTML

<div class="margins border">sibling</div> <div class="margins border float">floats1</div> <div class="margins border float">floats2</div>

1
2
3
<div class="margins border">sibling</div>
<div class="margins border float">floats1</div>
<div class="margins border float">floats2</div>

CSS

.margins{margin: 50px 0 50px;} .border{border: solid 1px red;} .float{float:left;width:200px;}

1
2
3
.margins{margin: 50px 0 50px;}
.border{border: solid 1px red;}
.float{float:left;width:200px;}

图片 36

归纳FC、BFC和IFC                      

由于上述主要阐述inline/block-level box,因此通过“仅此而已”来简化BFC和IFC的内涵。下面我们稍微全面一点去理解BFC和IFC如何影响inline/block-level box。

FC(Formatting Context),用于初始化时设置盒子自身尺寸和排版规则。注意“初始化”,暗指positioning scheme采用的是normal flow,要知道floats和absolute positioning均不是默认/初始化值。也就是说我们在讨论FC及BFC和IFC时,均针对in-flow box而言的。
  BFC
**对于不产生新BFC的盒子**

  1. block-level boxes垂直排列,盒子的left outer edge与所在的containing block的左边相接触,默认情况下(width为auto时)right outer edge则与所在的containing block的右边相接触。即使存在floated的兄弟盒子。

XHTML

<div id="container" style="border:solid 2px red;"> <div id="left" style="float:left;width:300px;height:30px;background:yellow;opacity:0.2;"></div> <div id="right" style="height:30px;background:#999;"></div> </div>

1
2
3
4
<div id="container" style="border:solid 2px red;">
  <div id="left" style="float:left;width:300px;height:30px;background:yellow;opacity:0.2;"></div>
  <div id="right" style="height:30px;background:#999;"></div>
</div>

图片 37

虽然 div#left 浮点了,但 div#right 的left outer edge还是与 div#container 的left content edge相接触。 div#right 所在的containing block就是 div#container 的content box.

  1. block-level box高度的计算
    The element’s height is the distance from its top content edge to the first applicable of the following:
    the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
    the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child’s bottom margin does not collapse with the element’s bottom margin
    the bottom border edge of the last in-flow child whose top margin doesn’t collapse with the element’s bottom margin
    zero, otherwise
    Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored, and relatively positioned boxes are considered without their offset).

也就out-flow box不影响block-level box高度的计算。也就是解释了为何div中仅含floated元素时,div盒子高度为0的现象了。

**对于产生新BFC的盒子**
对于产生新BFC的盒子而言,除了不发生collapsing margins的情况外,还有两个与浮点相关的现象。

  1. out-flow box纳入block-level box高度的计算
    In addition, if the element has any floating descendants whose bottom margin edge is below the element’s bottom content edge, then the height is increased to include those edges. Only floats that participate in this block formatting context are taken into account, e.g., floats inside absolutely positioned descendants or other floats are not.
    也就positioning scheme为floats的box也会影响block-level box高度的计算。

  2. 誓死不与positioning scheme为floats的兄弟盒子重叠
    The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with ‘overflow’ other than ‘visible’) must not overlap the margin box of any floats in the same block formatting context as the element itself. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space. They may even make the border box of said element narrower than defined by section 10.3.3. CSS2 does not define when a UA may put said element next to the float or by how much said element may become narrower.

产生新BFC的block-level box不与floated-box重叠,而是floated-box的margin-box与block-level box的border-box相接触。
水平方向

XHTML

<div style="float:left;width:100px;border: solid 1px red;margin-right:50px;">floated</div> <div style="width:200px;border: solid 1px blue;margin-left:100px;overflow:hidden;">gen new BFC balabala</div>

1
2
<div style="float:left;width:100px;border: solid 1px red;margin-right:50px;">floated</div>
<div style="width:200px;border: solid 1px blue;margin-left:100px;overflow:hidden;">gen new BFC balabala</div>

图片 38
垂直方向

XHTML

<div style="float:left;width:100px;border: solid 1px red;margin-bottom:50px;">floated</div> <div style="width:200px;border: solid 1px blue;margin-top:100px;overflow:hidden;">gen new BFC balabala</div>

1
2
<div style="float:left;width:100px;border: solid 1px red;margin-bottom:50px;">floated</div>
<div style="width:200px;border: solid 1px blue;margin-top:100px;overflow:hidden;">gen new BFC balabala</div>

图片 39

 

 IFC

提起IFC那就不能不说line box,而line box高度的计算方式上面已经叙述了,那line box的宽度呢?
line box默认情况下左边框与containing block的左边框接触,右边框与containing block的右边框接触。若存在floated兄弟盒子,则line box的宽度为containing block的宽度减去floated-box的outer-box的宽度。
图片 40
而inline-level box必须包含在line box中,若inline-level box的white-space:nowrap或pre外的其他值时,就会将inline-level box拆分为多个inline-level box并散落到多个line box中,从而实现文字环绕图片的效果了。
图片 41
否则inline-level box会捅破line box(即line box宽度不变)

    行——换与不    

先看看关于换行的CSS属性吧!

white-space normal: 忽略/合并空白 pre: 保留空白,如同<pre>的行为 nowrap: 忽略/合并空白,文本不会换行,直到遇到<br/> pre-wrap: 保留空白,但是会正常地进行换行 pre-line: 忽略/合并空白,但是会正常地进行换行 inherit: 从父元素继承。 word-wrap normal: 只在允许的断字点换行 break-word: 在长单词或URL地址内部进行换行 word-break normal:依照亚洲和非亚洲语言的文本规则,允许在单词内换行。 keep-all:让亚洲语言文本如同非亚洲语言文本那样不允许在任意单词内换行。 break-all:允许非亚洲语言文本行如同亚洲语言文本那样可以在任意单词内换行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
white-space
    normal: 忽略/合并空白
    pre: 保留空白,如同<pre>的行为
    nowrap: 忽略/合并空白,文本不会换行,直到遇到<br/>
    pre-wrap: 保留空白,但是会正常地进行换行
     pre-line: 忽略/合并空白,但是会正常地进行换行
    inherit: 从父元素继承。
  word-wrap
    normal: 只在允许的断字点换行
    break-word: 在长单词或URL地址内部进行换行
  word-break
    normal:依照亚洲和非亚洲语言的文本规则,允许在单词内换行。
    keep-all:让亚洲语言文本如同非亚洲语言文本那样不允许在任意单词内换行。
    break-all:允许非亚洲语言文本行如同亚洲语言文本那样可以在任意单词内换行。

具体示例可参考:css中强制换行word-break、word-wrap、white-space区别实例说明

在处理换行问题上,我们要处理的对象分为亚洲语言文本和非亚洲语言文本。对于亚洲语言文本是以字作为操作单元,而非亚洲语言文本是以单词作为操作单元。而换行是针对特定语言文本的操作单元来处理,所以默认情况下会看到一串没空格的“中文”自动换行,而一串没空格的“英文”却没有换行的现象。
对于我们(亚洲人)而言,一般采用 word-break:break-all;word-wrap:break-word; 来实现中英文自动换行效果,但英文单词本身是不能这样简单粗暴地换行的。
英语单词移行有一定规则,归纳如下:
1.移行处要用连字符号“-”,只占一个印刷符号的位置并放在该行的最后.
2.移行时一般按照音节进行,故只可在两音节之间分开,不能把一个完整的音节分写在上下两行.例如:Octo-ber(正),Octob-er(误).
3.复合词要在构成该词的两部分之间移行.如:some-thing,bed-room等.
4.如果复合词原来就有连字符号,则就在原连字符号处分行.如:good-looking等.
5.两个不同的辅音字母在一起时,移行时前后各一个.如:cap-tain,ex-pose等.
6.当两个音节间只有一个辅音字母时,如果该辅音字母前的元音字母按重读开音节的规则发音,该辅音字母移至下一行.如:fa-ther等.但如果元音按重读闭音节的规则发音,则该辅音字母保留在上一行末尾.例如:man-age等.
7.当遇到双写辅音字母时,一般把它们分成前后各一个.例如:mat-ter等.
8.当重读音节在后面时,元音字母前的辅音字母通常移到下一行.如:po-lite等.
9.单音节词不可移行.如:length,long,dance等.
10.前缀或后缀要保持完整,不可分开写.如:unfit,disappear等.
11.阿拉伯数字不分开移行书写.
12.不论音节多少,专有名词不宜分写.例如:Nancy,Russia等.
13.缩写词、略写词或某些词的缩写形式不可移行书写.例如:U.N.(联合国),P.R.C.(中华人民共和国),isn’t.
14.不能构成一个音节的词尾不分写.例如:stopped等.
15.字母组合或辅音连缀不可移行.例如:machine,meat等.

CSS简化了上述的规则,若需要换行处恰好是一个复合词,就在原连字符号处分行;其它情况则整个单词移到下一行。因此使用 word-wrap:break-word; 就OK了。

另外我们还可以通过 word-break:keep-all;white-space:nowrap; 来实现打死都不换行的效果
总结                              
洋洋洒洒总算把Box Model、BFC和IFC描述了个大概。对于BFC折腾点就是在collapsing margins那,另外还有产生新BFC这个行为上(这个跟浮动等有交集,以后再理清吧);而IFC重点在于理解line box,其实line box也像block-level box那样是垂直排列的,而inline-level box则是以line box作为容器实现水平排列罢了。到这里会发现理解IFC比BFC蛋疼多了,不过有了这篇作基础,后面理解text-align、line-height和vertical-align就轻松不少了。

本文纯个人理解,若有纰漏,望各位指正,谢谢!

感谢                              

)

)

(IFC)

[KB010: 常规流( Normal flow ) ]()
[CSS 101: Block Formatting Contexts]()

打赏支持我写出更多好文章,谢谢!

打赏作者

通过创建BFC翻身做主人

同样是盒子,为啥你就可以在我上面呢?你有Float罩着,我也找弄个新的BFC来跟你抗衡。我们知道通过float:left|rightposition:absolute|fixeddisplay:inline-block|table-cell|table|table-captionoverflow:auto|scroll|hidden均可让盒子产生新的BFC。而产生BFC的盒子间天生排斥彼此。(但可通过后天的努力position:relative让他们又互有交集^_^)
那现在的问题是采用Normal flow定位模式的会产生新的BFC的盒子到底是紧跟在Float定位盒子的后面,还是另起一行呢?答案是两者都有可能,具体看剩余的宽度是否足以容纳该盒子。其实就是如同设置父容器产生BFC,而该盒子采用Float定位模式。不信,你看

XHTML

<div style="float:left;border:solid 1px red;width:100px;height:50px;">float:left</div> <div style="background:#06f;width:200px;height:100px;overflow:hidden;"></div>

1
2
<div style="float:left;border:solid 1px red;width:100px;height:50px;">float:left</div>
<div style="background:#06f;width:200px;height:100px;overflow:hidden;"></div>

图片 42

BFC的范围

BFC的范围在MDN中是这样描述的。

A block formatting context contains everything inside of the element creating it that is not also inside a descendant element that creates a new block formatting context.

中文的意思一个BFC包含创建该上下文元素的所有子元素,但不包括创建了新BFC的子元素的内部元素。

这段看上去有点奇怪,我是这么理解的,加入有下面代码,class名为.BFC代表创建了新的块格式化:

XHTML

<div id='div_1' class='BFC'> <div id='div_2'> <div id='div_3'></div> <div id='div_4'></div> </div> <div id='div_5' class='BFC'> <div id='div_6'></div> <div id='div_7'></div> </div> </div>

1
2
3
4
5
6
7
8
9
10
<div id='div_1' class='BFC'>
<div id='div_2'>
<div id='div_3'></div>
<div id='div_4'></div>
</div>
<div id='div_5' class='BFC'>
<div id='div_6'></div>
<div id='div_7'></div>
</div>
</div>

这段代码表示,#div_1创建了一个块格式上下文,这个上下文包括了#div_2#div_3#div_4#div_5。即#div_2中的子元素也属于#div_1所创建的BFC。但由于#div_5创建了新的BFC,所以#div_6#div_7就被排除在外层的BFC之外。

我认为,这从另一方角度说明,一个元素不能同时存在于两个BFC中

BFC的一个最重要的效果是,让处于BFC内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。这是利用BFC清除浮动所利用的特性,关于清除浮动将在后面讲述。

如果一个元素能够同时处于两个BFC中,那么就意味着这个元素能与两个BFC中的元素发生作用,就违反了BFC的隔离作用,所以这个假设就不成立了。

浮动闭合

就是让height:auto的父容器包裹所有子元素,包括Float定位的子元素。方式很简单,就是好让父容器产生BFC。

浮动(Floats)

  • 盒称为浮动盒(floating boxes);
  • 它位于当前行的开头或末尾;
  • 导致常规流环绕在它的周边,除非设置 clear 属性;

压榨line box

图片 43
文字环绕很明显就是活生生地把文字向两边挤,为”大哥”留下个位置,而且小弟们不要走太远,必须时刻拥护着大哥。那大哥是如何圈住小弟们的呢?那得借助外力——line box。文字是以字形(glyph)的形式渲染,和它同一行的inline-level boxes均位于同一个line box中。而line box可谓是夹在containing block和浮动盒子之间勉强生存。
图片 44

XHTML

<div style="overflow:hidden;line-height:1.5;background:#06F;"> <img src="john.png" style="float:left;margin:10px"/> These days it takes a diverse and complex collection of components to power a web browser. <img src="john.png" style="float:right;margin:10px"/>It’s fair to think of all those parts coming together as a single piece of machinery, and we often talk about our web platform as an “engine”. </div>

1
2
3
4
<div style="overflow:hidden;line-height:1.5;background:#06F;">
<img src="john.png" style="float:left;margin:10px"/>
These days it takes a diverse and complex collection of components to power a web browser. <img src="john.png" style="float:right;margin:10px"/>It’s fair to think of all those parts coming together as a single piece of machinery, and we often talk about our web platform as an “engine”.
</div>

若line box的宽度不足以容纳glyph和inline-level boxes时,会在下方产生N个新的line boxes并在必要时拆分inline-level boxes,然后将glyph和inline-level boxes分布到各行的line boxes当中。

实例一

CSS

<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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<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>

显示效果:

图片 45

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

同时,由于灰色框(’#box’)并没有创建BFC,因此在计算高度的时候,并没有考虑绿色框的区域(特性6:浮动区域不叠加到BFC区域上),发生了高度坍塌,这也是常见问题之一。

期待更美的文字环绕

有没有发现通过float:left|right我们仅能得到要么图片靠左要么图片靠右的文字环绕效果,那如果我们希望得到如下的四周环绕的效果呢?
图片 46
虽然已有案例是通过absolute positioning模拟出类似的效果,但布局排版固定导致无法适应大部分场景。如果有个float:both属性值那该多好啊!另外大家是否觉得以下的环绕效果更有艺术范呢?
图片 47
听说通过CSS3的shapes特性可以实现四周环绕和上面非四四方方的环绕效果,日后好好研究研究!
2016/04/19补充-参考《CSS网站布局实录-基于Web标准的网站设计指南(第2版)》的5.2.2 不规则文字环绕
图片 48

XHTML

<style type="text/css"> .article{ font-size: 14px; line-height: 1.5; text-align: justify; } .figure{ position: absolute; z-index: -1; } .figure-shape{ margin: 0; padding: 0; } .figure-shape li{ list-style-type:none; height: 1.5em; float: left; clear: left; } .figure-shape li:nth-child(1){ width: 150px; } .figure-shape li:nth-child(2){ width: 180px; } .figure-shape li:nth-child(3){ width: 180px; } .figure-shape li:nth-child(4){ width: 160px; } .figure-shape li:nth-child(5){ width: 148px; } .figure-shape li:nth-child(6){ width: 150px; } .figure-shape li:nth-child(7){ width: 148px; } .figure-shape li:nth-child(8){ width: 144px; } .figure-shape li:nth-child(9){ width: 136px; } </style> <div class="article"> <img src="./beyonce.jpg" class="figure"/> <ul class="figure-shape"><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul> 初中时候语文老师说我会是个写作天才,因为我写的东西足够真实,取材身边,造句简单,用语文书垫桌脚的同时翻烂了韩寒的1988,那时督促我已经成为她的习惯。时至今日再次遇见语文老师时候我惭愧的告诉她我已经不写文了,也没有像她说的那样成为一个天才,我只能微微一笑告诉她我至少还没停下笔。 </div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<style type="text/css">
.article{
  font-size: 14px;
  line-height: 1.5;
  text-align: justify;
}
.figure{
  position: absolute;
  z-index: -1;
}
.figure-shape{
  margin: 0;
  padding: 0;
}
.figure-shape li{
  list-style-type:none;
  height: 1.5em;
 
  float: left;
  clear: left;
}
.figure-shape li:nth-child(1){
  width: 150px;
}
.figure-shape li:nth-child(2){
  width: 180px;
}
.figure-shape li:nth-child(3){
  width: 180px;
}
.figure-shape li:nth-child(4){
  width: 160px;
}
.figure-shape li:nth-child(5){
  width: 148px;
}
.figure-shape li:nth-child(6){
  width: 150px;
}
.figure-shape li:nth-child(7){
  width: 148px;
}
.figure-shape li:nth-child(8){
  width: 144px;
}
.figure-shape li:nth-child(9){
  width: 136px;
}
</style>
<div class="article">
<img src="./beyonce.jpg" class="figure"/>
<ul class="figure-shape"><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul>
初中时候语文老师说我会是个写作天才,因为我写的东西足够真实,取材身边,造句简单,用语文书垫桌脚的同时翻烂了韩寒的1988,那时督促我已经成为她的习惯。时至今日再次遇见语文老师时候我惭愧的告诉她我已经不写文了,也没有像她说的那样成为一个天才,我只能微微一笑告诉她我至少还没停下笔。
</div>

三个定位方案

在定位的时候,浏览器就会根据元素的盒类型和上下文对这些元素进行定位,可以说盒就是定位的基本单位。定位时,有三种定位方案,分别是常规流,浮动已经绝对定位。

被埋没的志向——文字环绕

回忆一下我们一般什么时候会想用浮动呢?是多列布局还是多列布局呢:)?其实它向往的却是这个
图片 49
它想干的就是这个——文字环绕,而且CSS2中除了浮动外没有其他属性可实现上述的效果。
那到底如何理解它的实现原理呢?下面我们采取分步剖析的方式来深入探讨吧!

视觉格式化模型

视觉格式化模型(visual formatting model)是用来处理文档并将它显示在视觉媒体上的机制,它也是CSS中的一个概念。

视觉格式化模型定义了盒(Box)的生成,盒主要包括了块盒、行内盒、匿名盒(没有名字不能被选择器选中的盒)以及一些实验性的盒(未来可能添加到规范中)。盒的类型由display属性决定。

以Normal flow为基础

不管是Absolute positioning还是Float均以Normal flow作为定位基础,也就是说先假设有一个虚拟盒子以Normal flow进行定位,然后在这个基础上添加Float的特性并影响其他盒子的布局。而浮动定位对于盒子自身而言仅影响其在水平方向上的定位,因此对于inline-level box而言其垂直方向上的定位并没有发生变化,而对于block-level box而言因Collapsing margins的失效有可能会引起垂直方向上的移动。
图片 50

XHTML

<div style="background:#0f6;width:200px;height:50px;margin-bottom:50px;"></div> <div style="background:#f06;width:200px;height:50px;margin:50px 0;"></div> <div style="background:#06F;width:200px;height:50px;margin-top:50px;float:left;">float:left</div>

1
2
3
<div style="background:#0f6;width:200px;height:50px;margin-bottom:50px;"></div>
<div style="background:#f06;width:200px;height:50px;margin:50px 0;"></div>
<div style="background:#06F;width:200px;height:50px;margin-top:50px;float:left;">float:left</div>

值得注意的是,浮动定位的虚拟盒子实际上是不占空间的。因此才有后续的浮动闭合和清除浮动的事。

实例三

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

XHTML

<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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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>

图片 51

由于粉色框没有创建新的BFC,因此粉色框中白色块受到了绿色框的影响,被挤到了右边去了。先不管这个,看看白色块的margin。

清除浮动

就是为浮动影响的范围划边界。方式也很简单,就是以一个clear:left|right|both的盒子作为边界即可,其实就是引入空隙(clearance)。
首先clear属性仅对block-level box有效clear:left表示盒子的margin-left-edge不与浮动盒子接触,而clear:right表示盒子的margin-right-edage不与浮动盒子接触,clear:both自然是左右两条margin-edge均不与浮动盒子接触啦。有点虚,直接看疗效吧!

XHTML

<div style="float:left;width:200px;height:50px;background:#06F;">float:left</div> <div style="clear:left;width:200px;height:50px;background:#F60;">clear:left</div> <div style="float:right;width:200px;height:50px;background:#06F;">float:right</div> <div style="clear:right;width:200px;height:50px;background:#F60;">clear:right</div>

1
2
3
4
<div style="float:left;width:200px;height:50px;background:#06F;">float:left</div>
<div style="clear:left;width:200px;height:50px;background:#F60;">clear:left</div>
<div style="float:right;width:200px;height:50px;background:#06F;">float:right</div>
<div style="clear:right;width:200px;height:50px;background:#F60;">clear:right</div>

图片 52

简单地说就是float:leftclear:left来清除,float:rightclear:right来清除。而我们会发现一个怪异的现象,那就是设置clear:left|right|both的盒子的border top edge紧接着Float定位盒子的margin bottom edge,其实这是clearance来作祟。当设置clear:left|right|both的盒子A的border top edge与Float定位盒子B的margin box重叠时,那么就会在A的margin box和border top edge之间引入clearance,恰好让A的的border top edge恰好不与B的margin bottom edge重叠。

XHTML

<div style="margin-bottom:50px;background:#06F;height:100px;width:200px;float:left;"></div> <div style="margin-top:50px;border: solid 10px red;height:50px;width:200px;clear:left;"></div>

1
2
<div style="margin-bottom:50px;background:#06F;height:100px;width:200px;float:left;"></div>
<div style="margin-top:50px;border: solid 10px red;height:50px;width:200px;clear:left;"></div>

图片 53

BFC的创建方法

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

但其中,最常见的就是overflow:hiddenfloat:left/rightposition:absolute。也就是说,每次看到这些属性的时候,就代表了该元素以及创建了一个BFC了。

.clearfix方案

不管是浮动闭合也好,清除浮动也罢,我们的目的往往是两者结合——Float定位的范围与Normal flow定位的范围分明,且采用Normal flow的父容器包裹所有子元素。那么可归结为Normal flow的父容器包裹所有子元素。因此得到如下的HTML Markup

XHTML

<div class="container clearfix"> <!-- Float定位的范围 --> </div> <!-- Normal flow定位的范围 -->

1
2
3
4
<div class="container clearfix">
   <!-- Float定位的范围 -->
</div>
<!-- Normal flow定位的范围 -->

而具体的方案如下:
方案1

CSS

.clearfix::after{ content: "."; display: block; clear: both; line-height: 0; visibility: hidden; } .clearfix{ *zoom: 1; /*for IE5.5/6/7*/ }

1
2
3
4
5
6
7
8
9
10
.clearfix::after{
  content: ".";
  display: block;
  clear: both;
  line-height: 0;
  visibility: hidden;
}
.clearfix{
  *zoom: 1; /*for IE5.5/6/7*/
}

伪元素after表示创建一个display:block,innerText是content属性值的元素作为该元素的最后一个子元素。注意content属性值不能为空白,否则无法清除浮动。
方案2

CSS

.clearfix::after{ content: "u200B"; /*通过零宽空白字符,省略visibility属性*/ display: block; clear: both; line-height: 0; } .clearfix{ *zoom: 1; /*for IE5.5/6/7*/ }

1
2
3
4
5
6
7
8
9
.clearfix::after{
  content: "u200B"; /*通过零宽空白字符,省略visibility属性*/
  display: block;
  clear: both;
  line-height: 0;
}
.clearfix{
  *zoom: 1; /*for IE5.5/6/7*/
}

注意:若页面不是采用UTF-8编码方式,那么u200B表示的将不是零宽空白字符,从而导致方案2出问题。
方案3
由Nicolas Gallagher大湿提出的

CSS

.clearfix::before, .clearfix::after{ content: ""; display:table; } .clearfix::after{ clear: both; } .clearfix{ *zoom: 1; /*for IE5.5/6/7*/ }

1
2
3
4
5
6
7
8
9
10
.clearfix::before, .clearfix::after{
  content: "";
  display:table;
}
.clearfix::after{
  clear: both;
}
.clearfix{
  *zoom: 1; /*for IE5.5/6/7*/
}

这里有2个奇妙的地方:

  1. 通过display:table让即使content为空白时,也能独占据一行,且高度为0;(原理是display:table会生成一个block-level box包裹着伪元素after)
  2. 通过伪元素before消除父容器margin-top与第一个Normal flow的子元素的margin-top产生margin collapsing效果。

行内盒(inline box)

  • 当元素的CSS属性display的计算值为inlineinline-blockinline-table时,称它为行内级元素;
  • 视觉上它将内容与其它行内级元素排列为多行;典型的如段落内容,有文本(可以有多种格式譬如着重),或图片,都是行内级元素;
  • 行内级元素生成行内级盒(inline-level boxes),参与行内格式化上下文(inline formatting context)。同时参与生成行内格式化上下文的行内级盒称为行内盒(inline boxes)。所有display:inline的非替换元素生成的盒是行内盒;
  • 不参与生成行内格式化上下文的行内级盒称为原子行内级盒(atomic inline-level boxes)。这些盒由可替换行内元素,或 display 值为 inline-block 或inline-table 的元素生成,不能拆分成多个盒;

头痛的开始——基于Normal flow看Float

用割裂的方式理解float并不难,难就难在结合Normal flow看Float。下面我们一起来探讨吧!警告,前方高能,前方高能!!

从实际代码来分析BFC

讲了这么多,还是比较难理解,所以下面通过一些例子来加深对BFC的认识。

关于作者:^-^肥仔John

图片 54

偏前端的临栈工程师 个人主页 · 我的文章 · 5 ·    

图片 55

常规流(Normal flow)

  • 在常规流中,盒一个接着一个排列;
  • 块级格式化上下文里面, 它们竖着排列;
  • 行内格式化上下文里面, 它们横着排列;
  • positionstaticrelative,并且floatnone时会触发常规流;
  • 对于静态定位(static positioning),position: static盒的位置是常规流布局里的位置
  • 对于相对定位(relative positioning),position: relative,盒偏移位置由这些属性定义topbottomleftandright即使有偏移,仍然保留原有的位置,其它常规流不能占用这个位置。

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

图片 56 图片 57

1 赞 6 收藏 2 评论

实例四

利用同实例二中一样的方法,为粉色框创建BFC:

XHTML

<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>

1
2
3
4
5
6
7
8
<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>

图片 58

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

是”浮动闭合”还是”清除浮动”?

我想各位都看过各种版本的clearfix实现,而最简单粗暴的方式就是添加一个<div style="clear:both"></div>来清除浮动。我还听过另一个名称——”浮动闭合”,那到底两者有什么区别呢?在作区分之前我们先要明确问题的本身。
对于height:auto的容器而言,我们希望它能恰好包裹着所有子元素,但不幸的是采用浮动定位模式的子元素将不纳入父容器的高度计算当中,那就会出现子元素戳穿父容器的风险。
从之前的内容我们了解到文字和inline-level boxes会环绕Float定位的盒子,而block-level box则被它踩在脚下。但现在希望后续盒子不再与Float定位的盒子有任何瓜葛。
面对这两种需求,我们分别得出”浮动闭合”和”清除浮动”两套方案。

块盒(block box)

块盒有以下特性:

  • 当元素的CSS属性displayblocklist-item或 table时,它是块级元素 block-level;
  • 视觉上呈现为块,竖直排列;
  • 块级盒参与(块格式化上下文);
  • 每个块级元素至少生成一个块级盒,称为主要块级盒(principal block-level box)。一些元素,比如<li>,生成额外的盒来放置项目符号,不过多数元素只生成一个主要块级盒。

浮动真的是定位模式的一员吗?

我们可以通过position属性来设置Normal flow或Absoluting positioning,但却要通过float属性来设置Float,这让我一度怀疑Float到底是不是定位模式的一员呢?
我是这样理解的,Normal flow(包括Relative positioning)与Absoluting positioning是非我即你的关系,而Float和Relative positioning则是可叠加影响定位效果的关系,显然必须另设一个属性来设置更恰当。

总结

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

总结

重构了几次总算写完了,想写得清楚而又不哆嗦真心不易,继续努力:)

块格式化上下文

到这里,已经对CSS的定位有一定的了解了,从上面的信息中也可以得知,块格式上下文是页面CSS 视觉渲染的一部分,用于决定块盒子的布局及浮动相互影响范围的一个区域

切断关联看Float

‘float’
Value: left | right | none | inherit
Initial: none
Applies to: all
Inherited: no
当设置float:left后,元素对应的margin left edge会尽可能向所属的containing block的左边框靠近,若同一行中存在位于左侧的元素设置了float:left,则即会尽可能向该兄弟元素的margin right edge靠近.

XHTML

<div style="background:#06F;width:200px;height:100px;position:relative;left:20px;"> <div style="background:#1F0;width:50px;height:50px;float:right;"></div> <div style="background:#F60;width:50px;height:50px;float:right;"></div> </div>

1
2
3
4
<div style="background:#06F;width:200px;height:100px;position:relative;left:20px;">
  <div style="background:#1F0;width:50px;height:50px;float:right;"></div>
  <div style="background:#F60;width:50px;height:50px;float:right;"></div>
</div>

图片 59
(由于float:left突出不了效果,因此采用float:right作例子。其中蓝色区域就是containing block范围,绿和红色块采用向右浮动)
当设置浮动后,display:inline的实际值将被改写为display:block,因此不要再为display:inline;height:100px;line-height:0;float:left导致盒子content height为100px感到惊讶了。也不要为即使剩余空间不足以存放整个display:inline;float:left盒子,导致整个盒子下移到下一行排版而惊讶了.(若为Normal flow则会根据white-spacing、word-wrap和word-break决定盒子内部分内容换行,而不是整个盒子换行)简单来说并不是float:left让盒子具有不为五斗米折腰的气质,而是display:block的功劳,又由于浮动的盒子会以水平方向排版,因此我们可以以display:inline-block来理解浮动定位的水平排版和换行行为。

XHTML

<div style="background:#06F;width:200px;height:100px;"> <span style="background:yellow;width:100px;height:50px;float:left;">I'm span</span> <span style="background:#F01;width:110px;height:50px;float:left;">I'm span too</span> </div>

1
2
3
4
<div style="background:#06F;width:200px;height:100px;">
  <span style="background:yellow;width:100px;height:50px;float:left;">I'm span</span>
  <span style="background:#F01;width:110px;height:50px;float:left;">I'm span too</span>
</div>

图片 60
当设置浮动后,虽然display的实际值为block但就width:auto而言,我认为display更像是采用inline-block,宽度由子元素决定。这就是包裹性了!
(float:right同理,只是方向不同而已)
注意:在仅考虑浮动元素本身的前提下,float:left的效果与display:inline-block而父容器direction:ltr的效果是一样的,不同的是浮动元素不纳入父容器高度的计算当中

XHTML

<div style="border:solid 1px #06F;"> <span style="background:#F01;float:left;">float:left</span> </div> <br clear="both"/><br/> <div style="border:solid 1px #06F;"> <span style="background:#F01;display:inline-block;">float:none</span> </div>

1
2
3
4
5
6
7
<div style="border:solid 1px #06F;">
  <span style="background:#F01;float:left;">float:left</span>
</div>
<br clear="both"/><br/>
<div style="border:solid 1px #06F;">
  <span style="background:#F01;display:inline-block;">float:none</span>
</div>

图片 61

BFC的效果

就如刚才提到的,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.

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.

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).

简单归纳一下:

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

这么多性质有点难以理解,但可以作如下推理来帮助理解:html的根元素就是<html>,而根元素会创建一个BFC,创建一个新的BFC时就相当于在这个元素内部创建一个新的<html>,子元素的定位就如同在一个新<html>页面中那样,而这个新旧html页面之间时不会相互影响的。

上述这个理解并不是最准确的理解,甚至是将因果倒置了(因为html是根元素,因此才会有BFC的特性,而不是BFC有html的特性),但这样的推理可以帮助理解BFC这个概念。

前言

定位系统中第一难理解就是Normal flow,而第二就非Float莫属了,而Float难理解的原因有俩,1. 一开头我们就用错了;2. 它跟Normal flow靠得太近了。本文尝试理清Float的特性和行为特征,若有纰漏望各位指正。

学习BFC

2015/08/21 · CSS · BFC

原文出处: elcarim的博客   

BFC全称是Block Formatting Context,即块格式化上下文。它是CSS2.1规范定义的,关于CSS渲染定位的一个概念。要明白BFC到底是什么,首先来看看什么是视觉格式化模型。

CSS魔法堂:说说Float那个被埋没的志向

2016/05/10 · CSS · 2 评论 · float

本文作者: 伯乐在线 - ^-^肥仔John 。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

参考

视觉格式化模型 | MDN

块格式化上下文| MDN

CSS之BFC详解

W3C block-formatting

1 赞 5 收藏 评论

图片 62

匿名盒(anonymous box)

匿名盒也有份匿名块盒与匿名行内盒,因为匿名盒没有名字,不能利用选择器来选择它们,所以它们的所有属性都为inherit或初始默认值;

如下面例子,会创键匿名块盒来包含毗邻的行内级盒:

XHTML

<div> Some inline text <p>followed by a paragraph</p> followed by more inline text. </div>

1
2
3
4
5
<div>
    Some inline text
    <p>followed by a paragraph</p>
    followed by more inline text.
</div>

图片 63

本文由金沙棋牌发布于金沙棋牌官方平台,转载请注明出处:说说Float那个被埋没的志向,重新认识Box

关键词:

上一篇:构建打包优化,配置最佳实践

下一篇:没有了