11.19 CSS 弹性项

弹性项用来表示弹性容器中的元素

一般而言,弹性容器中的弹性项(flex item)表示其文档流(in-flow)内容中的框。

每一个弹性容器的文档流子元素都是一个弹性项,并且每一个直接包含在弹性容器内的连续文本被包裹在一个匿名的弹性项中。然而,只包含空格的匿名弹性项不会被渲染,就好像其display值为none。

<div style="display:flex">

    <!-- flex item: 块子元素 -->
    <div id="item1">block</div>

    <!-- flex item: 浮动子元素;浮动属性被忽略。 -->
    <div id="item2" style="float: left;">float</div>

    <!-- flex item: 行内内容的匿名块框 -->
    anonymous item 3

    <!-- flex item: 行内子元素 -->
    <span>
        item 4
        <!-- flex item不会被块分开 -->
        <div id=not-an-item>item 4</div>
        item 4
    </span>
</div>

一个弹性项为其内容建立了一个新的格式化上下文环境。格式化上下文的类型取决于它的display值。然而,弹性项本身是弹性级别(flex-level)的框,而不是块级框:参加其容器的弹性格式化上下文(FFC),而不是在一个块格式化上下文(BFC)中。

一个弹性项的display值会被块级化(blockified):如果弹性容器中的项目的display指定值为行内级(inline-level)的,则被计算为相应的块级(block-level)。

有一些display值会导致在原有box周围生成匿名box,那么最外面的box(也就是弹性容器的直接子元素)将成为弹性项。 比如,有两个相邻的表格单元(display为table-cell),其生成的外围匿名table框就成为弹性项。

如果弹性项的display属性为table,则table的包装块将成为弹性项,并且order和align-self属性将应用在该项目上。 任何标题框的内容都会计入table包装块的min-content和max-content尺寸的计算。不过,该弹性框最终尺寸的计算时,把table包装块的边缘和table块内容之间的距离全部当作table box的border+padding区域,这样table box就是该弹性项。

绝对定位的弹性容器子元素

弹性容器中的绝对定位子元素不参与弹性布局。但是,它却参与重新排序(order属性),并影响它们的绘制顺序。

上述绝对定位子元素的静态位置确定如下:把元素看作是弹性容器的唯一弹性项,并假设该元素和弹性容器的尺寸是固定的。

如果在该元素上设置 align-content: center,该元素的静态位置将在弹性容器的垂直轴线(cross axis)方向居中。

弹性项的内外边距(Margins 和 Paddings)

相邻弹性项的 margin 不合并。自动 margin 会在相应维度吸纳额外空间,可用于对齐和推开相邻弹性项。

弹性项的Z顺序(Z-Ordering)

弹性项的绘制和CSS2.1里定义的行内块(inline block)完全相同,除了把初始文档序替换成了修改后的文档序,而除了auto之外的z-index取值将创建一个堆栈上下文(stacking context),即使位置是静态的。

塌缩项(Collapsed Items)

把弹性项的visibility属性值设置为collapse将导致该项目成为塌缩弹性项,其效果类似于table-row或table-column: 塌缩弹性项从渲染中移除,但会保留一个"支架(strut)"以保持弹性行的垂直尺寸(cross-size)稳定。这样,如果一个弹性容器只有一个弹性行(flex line),动态collapsing或uncollapsing项目将确保对弹性容器的cross-size没有影响,不会导致其余页面布局的“晃动”。 塌缩后弹性行将重新包装,但是,多行弹性容器的cross-size可能变或不变。

虽然塌缩的弹性项并不被显示,它们仍然出现在格式化结构(formatting structure)中。 因此,不同于display:none项目,依赖于box的效果(比如自增长序号或animations和transitions)对塌缩项仍然起作用。

下面是一个弹性布局的侧边栏(sidebar)例子,visibility属性设置成collapse,用来动态地隐藏侧边栏导航的部分内容,但是这种视觉上的隐藏并不影响其宽度,即使最宽的项目("Architecture")是在一个塌缩部分中。 鼠标悬停(hover)在塌缩项上(这里是"Projects")时,隐藏内容将呈现出来而周边布局的宽高不发生变化。

计算strut的大小时,弹性布局先展示所有项目,然后把塌缩项逐个替换为维持原有cross-size的空白支架。在弹性布局算法章节,我们对此有明确定义。

注意:对任意弹性项应用visibility:collapse,将导致弹性布局算法的重复计算。因此如果项目无需动态塌缩和展示,建议作者继续使用display:none来隐藏项目,这使得布局引擎更高效。

隐含的弹性项最小尺寸

为了给弹性项提供更合理的最小尺寸,CSS3给min-width和min-height属性引入了新的初始值 auto

auto
在主轴线上的弹性项,overflow的值为visible,当指定弹性项主轴线方向上的min-size时,由下表确定:
指定尺寸(specified size) 调整尺寸(transferred size) 最小尺寸
内容尺寸(content size)
min(指定尺寸, 内容尺寸)
min(调整尺寸, 内容尺寸)
min(指定尺寸, 内容尺寸)
specified size
如果项目的主轴线尺寸(main size)计算值是明确定义的,则specified size就是该值(受限于定义的最大尺寸属性)。否则就是undefined。
transferred size
如果弹性项有一个内在宽高比,并且cross size属性是明确定义的,那么transferred size就是该通过宽高比转换来的size(受限于定义的最大和最小cross size)。否则就是undefined。
content size
content size是主轴线上的最小内容尺寸(min-content size),如果弹性项有一个内在宽高比,并且cross size属性是明确定义的,那么transferred size就是该通过宽高比转换来的size(受限于定义的最大和最小cross size), 然后进一步受限于定义的 max main size 属性。

如果不符合上述情况,auto被计算为0

为了防止循环计算尺寸,min-height 和 max-height 的 auto 值不计入box内容的百分比尺寸解析。比如,一个百分比高度的块,弹性项父元素的height: 120em; min-height: auto,那么其自身尺寸将根据 height: 120em 来计算,而和 min-height 属性无关。