块级、行内格式化上下文

此篇想法总访问 10 次,今日访问 1 次。

名词解释

FC

英文全称 Formatting Contexts,中文直译为格式化上下文。

BFC

英文全称Block Formatting Contects,中文直译为块级格式化上下文。

IFC

英文全称Inline Formatting Contexts,中文直译为行内格式化上下文。

GFC

英文全称GridLayout Formatting Contexts,中文直译为网格布局格式化上下文。

FFC

英文全称Flex Formatting Contexts,中文直译为自适应格式化上下文, 不过W3C规范中并没有提到FFC。

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.

浮动元素满足BFC条件;绝对定位的元素满足BFC条件;属于块级容器(类似 inline-bloacks, table-cells, 和 table-captions)但不属于块级盒子的元素满足BFC条件;还有是块级盒子元素但是它的 overflow 属性不是 visible的元素满足BFC条件(但是如果该属性值蔓延到了视窗则不能创建BFC);满足以上条件的都能为他们的子元素创建新的块级格式化上下文。

  • float 的值不为 none
  • position 的值不为 static 或 relative
  • display 的值为 table-cell、table-caption、inline-block、flex 或 inline-flex
  • overflow 的值不为 visibility

这里就引申出来如何清除浮动?有三种常见的方法:

使用伪元素 ::after,缺点是增加了不必要的CSS代码。

.item{
	float:left;
}
.item-wrap:after{
	display:block;
	content:'';
	clear:both;
}

增加一个div标签用于清除并阻隔浮动对后边元素的影响,缺点是增加了HTML代码和CSS代码

最简便方法是根据W3C规定的触发BFC创建新的格式化上下文的方法,阻隔对其他元素的影响。比如为这些浮动元素的父容器的overflow属性设置不是none的值即可(但是这里不能使用float设置为非none,否则还是会影响后续元素)。

.item-wrap{
	... /*其他代码*/
	overflow: hidden;
}

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

在块级格式化上下文中,每一个盒子的左边最外层都会触碰到容器的左边缘(对于从右至左的格式化来说,则都会碰到容器的右边缘)。即使有浮动元素的存在上一条规则也成立(尽管盒子内部的行内元素会因为浮动元素而被挤压缩),除非该盒子满足创建一个新块级格式化上下文(这种情况下,该盒子会由于其他浮动元素而自适应变得狭窄)。

IFC

关于 inline boxes 和 line boxes 的概念看帅华君画的这张图

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

在行内格式化上下文内,盒子们从容器块的顶部开始在水平方向上一个挨着一个的排列;这些水平方向上的盒子们的外边距,边框和内边距是可以被设置;这些盒子们可以以不同的方式垂直对齐:他们可以底部或顶部对齐,也可以通过文本的基线对齐;矩形区域包含着来自一行的盒子叫做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 的宽度由包含块和浮动情况决定。线盒子的高度由 line-height 计算得出。

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总是足够的高,以至于能包含住其内的所有盒子。然而,line box 可以比其内最高的盒子还要高(比如说,举个例子,盒子们被对齐导致基线被提高)。当盒子B的高度比包含他的line box的高度要低,lin box内盒子B的垂直对齐方式由 vertical-align 属性决定,当几个行内盒子不能在一个单独的盒子中适当的水平放置,他们会被分配给两个或更多的垂直栈上的 line box,因此,一个段落是很多line box的垂直栈。这些line box不会在垂直方向上被分离(除非在其他地方有特殊规定),并且他们也不重叠。

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在相同的行内格式化上下文中他们通常都有相同的宽度(包含块的宽度),但是水平方向上的空间因为浮动被减少了,但是水平方向上的空间因为浮动被减少了(比如,一行也许包含了一个最高的图片然后其他的也可以仅仅只包含文字)。

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-table 和 inline-block 除外)。

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中,如果inline box 不能给分割(比如,如果行内盒子只有单个字符,或者单词折行的规则不允许折行,或者行内盒子的 white-space 属性 设置了 nowrap 或者 pre 属性值),那么inline box会溢出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).

当inline box 被分割后,margins, borders 和 padding属性在视觉上便没有了效果(或者任何将它们分割成成几个的情况)。

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

同样的,同一个 line box 内的 inline boxs 也会因为双向文字处理而被分割成几个boxs。

[https://docs.oracle.com/javase/tutorial/2d/text/textlayoutbidirectionaltext.html](https://docs.oracle.com/javase/tutorial/2d/text/textlayoutbidirectionaltext.html)

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 boxes 会因为需要包裹inline-level的内容而创建行内格式化上下文。line boxes 包含没有文本,没有空格,没有带非零的margin,padding和borders的行内元素,以及没有其他在流中的内容(不如图像,行内块或者行内表格),并且不会以新的一行结束,必须将line boxes视作零高的盒子。

如下是一个典型的 inline box 结构的例子。下方段落(由HTML 块级元素p创建)包含无特征的文本,并由 EM元素 和 STRONG 元素装饰:

<P>Several <EM>emphasized words</EM> appear
<STRONG>in this</STRONG> sentence, dear.</P>

p元素产生一个块级盒子,包含5个inline boxes,其中有三个是无特征的:

  • Anonymous: “Several”
  • EM: “emphasized words”
  • Anonymous: “appear”
  • STRONG: “in this”
  • Anonymous: “sentence, dear.”

为了格式化该段落,用户代理将这5个盒子放入line boxes,在该示例中,为 P 元素产生了一个为line boxes创建容器块的盒子。如果容器块足够的宽,所有的 inline boxes 将会给放入单个的 line box:

 Several emphasized words appear in this sentence, dear.

如若不然,inline boxes 将会被分割并分配到几个line boxes中,上一段看起来会像这样:

Several emphasized words appear
in this sentence, dear.

或者更加的拥挤,像这样:

Several emphasized  
words appear in this
sentence, dear.

在上一个例子中,EM 盒子将会分割为两个 EM 盒子(我们就叫他 split1 和 split2 吧),作用在split1之后和split2之前的margins, borders, padding或者文本装饰将不会产生任何视觉效果。

考虑如下例子:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
  <HEAD>
    <TITLE>Example of inline flow on several lines</TITLE>
    <STYLE type="text/css">
      EM {
        padding: 2px;
        margin: 1em;
        border-width: medium;
        border-style: dashed;
        line-height: 2.4em;
      }
    </STYLE>
  </HEAD>
  <BODY>
    <P>Several <EM>emphasized words</EM> appear here.</P>
  </BODY>
</HTML>

由于p元素的宽度太窄,所以盒子会像下面这样被重新分配:

  • 给 “emphasized” 之前和 “words”之后设置了margin
  • 给“emphasized”的前、上、下和“words”的后、上、下设置了padding,还有每一种情况的三条边都设置了边框。

GFC

A grid container establishes a new grid formatting context for its contents. This is the same as establishing a block formatting context, except that grid layout is used instead of block layout: floats do not intrude into the grid container, and the grid container’s margins do not collapse with the margins of its contents. The contents of a grid container are laid out into a grid, with grid lines forming the boundaries of each grid items’ containing block. The overflow property applies to grid containers.

网格容器会为它的内容创建新的网格格式化上下文。和创建一个块级格式化上下文几乎一模一样,除了以下几个不同之处以外:浮动不会干扰网格容器,并且网格容器的margin不会相互塌陷。网格容器的内容在网格中排列着,网格线为每一个网格项目的包含块形成了边界。overflow属性适用于网格容器。

Grid containers are not block containers, and so some properties that were designed with the assumption of block layout don’t apply in the context of grid layout. In particular:

网格容器不是块级容器,并且一些为块级元素设计的属性是不适用与网格布局的,比如:

  • float and clear have no effect on a grid item. However, the float property still affects the computed value of display on children of a grid container, as this occurs before grid items are determined.
    float 和 clear 属性对网格项目不起作用。然而,float 属性仍然网格容器的子元素的 display 属性的计算值,在这之前网格项目就已经确定了。

  • vertical-align has no effect on a grid item.
    vertical-align 属性对网格项目不起作用。

  • the ::first-line and ::first-letter pseudo-elements do not apply to grid containers, and grid containers do not contribute a first formatted line or first letter to their ancestors.
    ::first-line 和 ::first-letter 微元素不适用于网格容器,并且网格容器不会为其祖先元素提供第一个格式化的行或者第一个字符。

If an element’s specified display is inline-grid and the element is floated or absolutely positioned, the computed value of display is grid. The table in CSS 2.1 Chapter 9.7 is thus amended to contain an additional row, with inline-grid in the “Specified Value” column and grid in the “Computed Value” column.

如果一个元素制定显示方式为 inline-grid 并且该元素为浮动定位或者绝对定位,则display的计算值就是grid。

FFC

W3C并没有提出FFC的概念。不过display属性值设置为flex,便可以创建一个弹性布局。

阮一峰的这篇Flex布局教程:语法篇值得一看>Flex布局教程:语法篇值得一看

发布日期 » 2017年11月4日 周六
原创声明 » 请勿复制转载,谢谢配合。
Airglass.js核心库
JavaScript核心概念
硬件编程、Arduino
文档翻译计划
微信开发
前端脚手架
运维
可视化
生活自有“道”理
视觉设计、用户体验
陈帅华的微信二维码