10

一、盒子模型

页面任何一个元素都可以看成是box,box分block-level,inline-level和匿名的。

匿名box:
    <div>
        Some text
        <p>More text</p>
    </div>
其中"Some text",浏览器会为其生成一个匿名box

二、BFC

什么是BFC?

BFC的全称是Block Formatting Context,直译过来是:块级格式化上下文。

在理解BFC时先理解三个概念:

1、Block-level elements
属于diplay: block;的元素,都是Block-level elements(块级元素);有可能会触发BFC。

2、block boxes
W3C规范原文的定义:"Block-level boxes that are also block containers are called block boxes."可以作为block containers的块级元素,称为block boxes

3、block container box
原文:"a block-level box is also a block container box"。

最后还有一句:"The three terms "block-level box," "block container box," and "block box" are sometimes abbreviated as "block" where unambiguous."

都简称为块级元素好了orz...为什么要纠结这个?主要是被规范的用词搞晕了,花了点时间才搞明白这三个词的意思。

BFC的布局规矩:


1、内部box在垂直方向,一个接一个的放置;
2、box的垂直方向由margin决定,属于同一个BFC的两个box间的margin会重叠
3、BFC区域不会与float box重叠(可用于排版);
4、BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
5、计算BFC的高度时,浮动元素也参与计算

哪些元素或属性会触发BFC?

1、根元素;
2、float属性不为none;
3、position为absolute或fixed;
4、display为inline-block, flex, 或者inline-flex;
5、overflow不为visible;

扒了下 W3C的文档,里面对BFC的解释是酱紫的:

"9.4.1 Block formatting contexts

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

For information about page breaks in paged media, please consult the section on allowed page breaks."

三、IFC

同理,IFC是Inline formatting context。

规范 里,IFC的描述比BFC的描述多很多,原文比较长,一点点扒吧:

an inline formatting context, boxes are laid out horizontally, one after the other, beginning at the top of a containing block. Horizontal margins, borders, and padding are respected between these boxes. The boxes may be aligned vertically in different ways: their bottoms or tops may be aligned, or the baselines of text within them may be aligned. The rectangular area that contains the boxes that form a line is called a line box.

在一个IFC中,从父级元素的顶部开始,盒子一个接一个横向排列。此时,横向的margin、borders、padding在这些盒子中都是有效的。这些盒子有可能通过不同的方式垂直对齐:1、他们底部或者顶部可以对齐,2、或者可以他们内部的文字基线可以对齐。如果一个矩形区域,包含着一些排成一条线的盒子,称为line box。

The width of a line box is determined by a containing block and the presence of floats. The height of a line box is determined by the rules given in the section on line height calculations.

一个line box的宽度,由他的包含块(containg block)和floats的存在情况决定。linebox的高度,由你给出的代码决定。

A line box is always tall enough for all of the boxes it contains. However, it may be taller than the tallest box it contains (if, for example, boxes are aligned so that baselines line up). When the height of a box B is less than the height of the line box containing it, the vertical alignment of B within the line box is determined by the 'vertical-align' property. When several inline-level boxes cannot fit horizontally within a single line box, they are distributed among two or more vertically-stacked line boxes. Thus, a paragraph is a vertical stack of line boxes. Line boxes are stacked with no vertical separation (except as specified elsewhere) and they never overlap.

一般line box的高度对于子元素而言总是够用的,不过有可能比他包含的最高的元素还高(如果这样,内部包含的盒子会对齐,基线排成一排)。当盒子的高度小于父级盒子高度时,垂直方向的对齐由‘vertical-align’属性决定(疑问:原文的box B是啥??)。
当几个内联盒子在line box一行内放不下时,它们会分布在两个以上的垂直并列(vertically-stacked)的line box上。因此,一个段落都是一堆line box堆叠在一起。line box在垂直堆叠的时候,不会有分离(no vertical separation)而且绝不会重叠(其他特殊情况除外【啥特殊情况??】)

In general, the left edge of a line box touches the left edge of its containing block and the right edge touches the right edge of its containing block. However, floating boxes may come between the containing block edge and the line box edge. Thus, although line boxes in the same inline formatting context generally have the same width (that of the containing block), they may vary in width if available horizontal space is reduced due to floats. Line boxes in the same inline formatting context generally vary in height (e.g., one line might contain a tall image while the others contain only text).

一般来说,line box和内部元素,都是左挨左,右挨右。不过浮动盒子可能会在包含块和line box的边缘之间。因此,即使line box在同一个IFC里通常有相同的宽度。如果他们横向间距会因float减少,它们宽度可能会不一样。line box在同一个IFC高度可能不一样(e.x.:含有不同高度的image)

When the total width of the inline-level boxes on a line is less than the width of the line box containing them, their horizontal distribution within the line box is determined by the 'text-align' property. If that property has the value 'justify', the user agent may stretch spaces and words in inline boxes (but not inline-table and inline-block boxes) as well.

当内联盒子的总宽度比line box小的时候,它们的水平分布由'text-align'属性决定。如果该属性值为'justify',用户可以拓宽在inline box的空间和文字。

When an inline box exceeds the width of a line box, it is split into several boxes and these boxes are distributed across several line boxes. If an inline box cannot be split (e.g., if the inline box contains a single character, or language specific word breaking rules disallow a break within the inline box, or if the inline box is affected by a white-space value of nowrap or pre), then the inline box overflows the line box.

如果内联盒子的宽度超过了line box,内联盒子会被分解成几个盒子,然后分布在几个line box里面。如果内联盒子不能被分解(e.g.,如果内联盒子有单个单词、或者有特殊的换行规则,或者被'white-space'的'nowrap'、'pre'影响),它会超过line box。

When an inline box is split, margins, borders, and padding have no visual effect where the split occurs (or at any split, when there are several).

如果一个内联盒子被分解了,margins、borders、和padding在他们被分解的位置没有视觉效果。

Inline boxes may also be split into several boxes within the same line box due to bidirectional text processing.

由于双向文本处理(bidirectional text processing)内联盒子有可能在同一个line box里被分解成不同的盒子。

Line boxes are created as needed to hold inline-level content within an inline formatting context. Line boxes that contain no text, no preserved white space, no inline elements with non-zero margins, padding, or borders, and no other in-flow content (such as images, inline blocks or inline tables), and do not end with a preserved newline must be treated as zero-height line boxes for the purposes of determining the positions of any elements inside of them, and must be treated as not existing for any other purpose.

line box主要被用来在IFC内装载内联级内容。不包含文本、不预留空白、没有非零margins,padding,border 或者其他flow内容(images、 inline block 或者 inline tables)的内联元素的line box必须被当成零高度的line box,主要为了定位其他在其里面的元素,还有必须被当成不存在的或者其他目的(这是什么鬼???看不懂)。

参考资料:

W3C规范:http://www.w3.org/TR/CSS2/visuren.html
MDN的介绍:https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Visual_formatting_model
知乎一个很棒的答案:https://www.zhihu.com/question/20086234

lapsec
756 声望25 粉丝