9.5 浮动(done) - acelan86/css GitHub Wiki

毛xx说:浮动布局是个好布局啊

译者说:就是TMD用不好,坑太多


浮动是指一个盒在当前行中被变换到左边或者右边。浮动最有意思的特点是内容将沿着它的边缘放置(或者可以通过“clear”属性阻止它们这么做)。内容从一个左浮盒的右边往下或者从一个右浮盒的左边往下放置。下面是对浮动定位方式和内容流的介绍;“float”属性的描述给出了精确的控制浮动行为的规则。

A float is a box that is shifted to the left or right on the current line. The most interesting characteristic of a float (or "floated" or "floating" box) is that content may flow along its side (or be prohibited from doing so by the 'clear' property). Content flows down the right side of a left-floated box and down the left side of a right-floated box. The following is an introduction to float positioning and content flow; the exact rules governing float behavior are given in the description of the 'float' property.

一个浮动盒被变换到左边或者右边直到它的外边缘接触到包含盒的边缘或者他的外边缘接触到另外一个浮动元素。如果在一个line box中,浮动盒的外顶部和当前line box的顶部对齐。

A floated box is shifted to the left or right until its outer edge touches the containing block edge or the outer edge of another float. If there is a line box, the outer top of the floated box is aligned with the top of the current line box.

如果没有足够的水平空间容纳浮动元素,它会往下直到有合适的空间放置或者不再有浮动元素存在。

If there is not enough horizontal room for the float, it is shifted downward until either it fits or there are no more floats present.

因为浮动元素不在流中,非定位块盒会在浮动盒的前后垂直放置,就像浮动元素不存在一样。但是,紧邻浮动元素创建的当前和随后的line box必须被缩短以使得有空间容纳浮动元素的margin box(译注:这里指content box,boder box类似的这样的概念,就是浮动元素包含margin的那个区域)。

Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float did not exist. However, the current and subsequent line boxes created next to the float are shortened as necessary to make room for the margin box of the float.

当存在一个垂直位置全部满足下面四个条件时,一个line box可以跟浮动元素紧挨:

  1. 在line box顶部上或在line box顶部的下面。(at or below)。
  2. 在line box底部上或在line box底部的上面。(at or above)。
  3. 在浮动元素顶部margin边缘的下面。(below)。
  4. 在浮动元素底部margin边缘的上面。(above)。

A line box is next to a float when there exists a vertical position that satisfies all of these four conditions:

  • (a) at or below the top of the line box
  • (b) at or above the bottom of the line box
  • (c) below the top margin edge of the float
  • (d) above the bottom margin edge of the float.

*注意:这里意味着0高度或者负高度的float元素不会缩短line box。

译注: 这是为什么类?我为毛得不出来?跪大神指教

Note: this means that floats with zero outer height or negative outer height do not shorten line boxes.

如果一个缩短line box对于它的内容来说太小,那么line box将被向下移动(它的宽度将被重新计算)直到内容合适或者不在存在浮动元素。任何在当前行内,在这个浮动盒之前的内容将被在浮动元素的另一边重新排布(与float在同一行)。换句话说,如果行内级盒被放置在一个左浮的盒子之前的行中并且除去浮动元素后剩下的line box空间正好合适的话,这个左浮元素会被放置在那行中,与line box的顶部对齐,然后该行中这个先前的行内级盒将相应的移动到浮动元素的右边(这个右边是左浮元素的另外一边),对于rtl和右浮元素亦是如此。

If a shortened line box is too small to contain any content, then the line box is shifted downward (and its width recomputed) until either some content fits or there are no more floats present. Any content in the current line before a floated box is reflowed in the same line on the other side of the float. In other words, if inline-level boxes are placed on the line before a left float is encountered that fits in the remaining line box space, the left float is placed on that line, aligned with the top of the line box, and then the inline-level boxes already on the line are moved accordingly to the right of the float (the right being the other side of the left float) and vice versa for rtl and right floats.

table, 块级可被重放置元素(有内置行高的元素),或者正常流中建立了一个新的块格式化上下文的元素(例如拥有除了“visible”的值外的值的“overflow”属性的元素)的border box必须不与在同一个格式化上下文中的任何浮动元素的margin box重叠。如果有这种必要, 实现必须通过把上述元素放置在任何浮动元素下面来清除它,但如果有足够的空间的话它可以毗邻这样的浮动元素被放置。它们甚至可能使得上述元素的border box比10.3.3章定义的更窄。CSS2没有定义一个客户端代理应该怎样紧邻浮动放置上述的元素或者上述的元素应该变窄多少。

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.

例子。在下面的文档片段中,包含块太窄以至于无法包含和浮动元素相邻的内容,因此内容被移动到浮动元素的下面,它在line box中的对齐取决于text-align属性。

Example. In the following document fragment, the containing block is too narrow to contain the content next to the float, so the content gets moved to below the floats where it is aligned in the line box according to the text-align property.

p { width: 10em; border: solid aqua; }
span { float: left; width: 5em; height: 5em; border: solid blue; }
...
<p>
  <span> </span>
  Supercalifragilisticexpialidocious
</p>

这个片段看起来像这样:

This fragment might look like this:

浮动

多个浮动元素是紧邻的,而且这个模型也应用于相同行中的紧邻的浮动元素。

Several floats may be adjacent, and this model also applies to adjacent floats in the same line.

下面的规则通过class=“icon”将所有的img盒浮动到左边(并且设置margin为0):

The following rule floats all IMG boxes with class="icon" to the left (and sets the left margin to '0'):

img.icon { 
  float: left;
  margin-left: 0;
}

思考下面的HTML源代码和样式表:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
  <HEAD>
    <TITLE>Float example</TITLE>
    <STYLE type="text/css">
      IMG { float: left }
      BODY, P, IMG { margin: 2em }
    </STYLE>
  </HEAD>
  <BODY>
    <P><IMG src=img.png alt="This image will illustrate floats">
       Some sample text that has no other...
  </BODY>
</HTML>

IMG盒被浮动到左边。随后的内容被格式化到浮动元素的右边,从与浮动元素相同的行开始。由于浮动元素的存在,浮动右边的line box太短,但在浮动的后面(译注:这里指这个浮动不在占据空间的地方)回到它们的“normal(正常)”宽度(P元素建立的包含块的宽度)。这个文档可能被像下面那样格式:

The IMG box is floated to the left. The content that follows is formatted to the right of the float, starting on the same line as the float. The line boxes to the right of the float are shortened due to the float's presence, but resume their "normal" width (that of the containing block established by the P element) after the float. This document might be formatted as:

浮动 D

如果文档是下面这样,格式化将会完全一致:

Formatting would have been exactly the same if the document had been:

<BODY>
  <P>Some sample text 
  <IMG src=img.png alt="This image will illustrate floats">
           that has no other...
</BODY>

因为浮动元素左边的内容沿着浮动元素显示并且从它的右边重新向下排布。

because the content to the left of the float is displaced by the float and reflowed down its right side.

译注:这里应该是有前提的,即如果浮动前面的文本内容只有一行,且水平空间除去浮动后足够在一行内容纳这个文本的情况下,两个写法的布局精确的一致,请见example4.html和example5.html的展示。 或者这里的意思只是它们的格式化方法一致,并不是说展现后的结果一致。

就像8.3.1节描述的那样,浮动盒子的margin不会和相邻的盒子的margin折叠。也就是说,在前面的这个例子中,浮动的img盒子跟p盒子之间的margin不会折叠。

As stated in section 8.3.1, the margins of floating boxes never collapse with margins of adjacent boxes. Thus, in the previous example, vertical margins do not collapse between the P box and the floated IMG box.

浮动元素的内容被堆积就像浮动元素生成了新的堆叠上下文(stacking contexts),除了那些定位和确实创建了堆叠上下文参与了浮动元素的父元素的堆叠上下文的元素。正常流中浮动元素能够覆盖其他盒(例如,当一个拥有负margin的正常流的盒子与一个浮动元素紧邻时)。当这种情况发生时,浮动元素被渲染在非定位的流内块的前面,但在流内的行内元素后面。

读者注: 浮动元素在流内的行内元素后面例子 ,更多例子understand float---by fedeoo

The contents of floats are stacked as if floats generated new stacking contexts, except that any positioned elements and elements that actually create new stacking contexts take part in the float's parent stacking context. A float can overlap other boxes in the normal flow (e.g., when a normal flow box next to a float has negative margins). When this happens, floats are rendered in front of non-positioned in-flow blocks, but behind in-flow inlines.

这里有另外一个图例, 展现了正常流中一个浮动元素覆盖元素border的时候的情况。

Here is another illustration, showing what happens when a float overlaps borders of elements in the normal flow.

浮动 D

一个浮动的图片遮盖了和它重叠的块盒的边框。

下面的例子表明“clear”属性的用法,用来防止内容紧随一个浮动元素放置。

The following example illustrates the use of the 'clear' property to prevent content from flowing next to a float.

假定一个像这样的规则:

Assuming a rule such as this:

p{clear: left}

格式化结果看起来像这样:

formatting might look like this:

清除浮动 D

两个段落都被设置了“clear:left”属性,这导致了第二个段落被“往下推”到浮动元素的下方——“空隙”被添加到它的上margin处以达到这个效果(见“clear”属性)。

9.5.1 定位浮动元素:“float”属性

“float”

Value: left | right | none | inherit

Initial: none

Applies to: all, but see 9.7

Inherited: no

Percentages: N/A

Media: visual

Computed value: as specified

本属性描述了一个盒子左浮,右浮或者什么都不做。它可以被设置到任何元素中,但只在元素生成的盒子不是绝对定位的情况下生效。这个属性的值的意义如下:

This property specifies whether a box should float to the left, right, or not at all. It may be set for any element, but only applies to elements that generate boxes that are not absolutely positioned. The values of this property have the following meanings:

left 元素生成一个浮动到左边的块盒。内容从盒子的顶部,在盒子的右侧排布。

The element generates a block box that is floated to the left. Content flows on the right side of the box, starting at the top (subject to the 'clear' property).

right

和“left”类似,除了盒子是浮动到右边,内容从盒子的顶部起,在盒子的左侧排布。

Similar to 'left', except the box is floated to the right, and content flows on the left side of the box, starting at the top.

none

盒子不浮动。

The box is not floated.

用户代理对根元素上的“float”属性以“none”对待。

User agents may treat float as 'none' on the root element.

译注:即根元素上的float属性无效。

这里有一些控制浮动元素行为的精确规则:

Here are the precise rules that govern the behavior of floats:

  1. 一个左浮盒子的左外边缘不会在它的包含块的左边缘的左边。右浮元素也保持相似的规则。
  2. 如果当前的盒子是左浮的,且源文档中存在较早的生成的左浮的盒子的元素,那么对于每一个这样的早期盒子,当前盒子的左外边必须在这个早先的盒子的右外边缘的右边,或者它的顶部必须低于早先的盒子的底部。右浮盒子也保持相似的规则。
  3. 一个左浮盒子的右外边缘不能在任何与它相邻的右浮元素的左外边缘的右边。右浮元素也保持相似的规则。
  4. 一个浮动盒子的外顶部不能比它的包含盒更高。当浮动在两个折叠的margin间发生的时候,浮动元素的定位就像它拥有另外一个空的父级匿名块。这样一种父级定位在margin collapsing这个章节定义
  5. 一个浮动盒的外顶部不能高于任何块或者由源文档中更早的元素生成的浮动盒的外顶部。
  6. 一个元素的浮动盒的外顶部不能高于任何由源文档中更早的元素生成的line-box包含一个盒子的顶部。
  7. 左边有另外一个左浮盒子的左浮盒子的右外边缘不能在它的包含块的右边缘的右边。(不严格的说:一个左浮元素不能超出右边缘,除非它已经尽可能的的放在左边。)右浮元素也保持相似的规则。
  8. 浮动盒必须尽可能的往高处放。
  9. 左浮盒子必须尽可能的放在左边,右浮盒子必须尽可能的放在右边。一个更高的位置优先分配给距离左/右更远的元素。

Here are the precise rules that govern the behavior of floats:

  1. The left outer edge of a left-floating box may not be to the left of the left edge of its containing block. An analogous rule holds for right-floating elements.
  1. If the current box is left-floating, and there are any left-floating boxes generated by elements earlier in the source document, then for each such earlier box, either the left outer edge of the current box must be to the right of the right outer edge of the earlier box, or its top must be lower than the bottom of the earlier box. Analogous rules hold for right-floating boxes.
  2. The right outer edge of a left-floating box may not be to the right of the left outer edge of any right-floating box that is next to it. Analogous rules hold for right-floating elements.
  3. A floating box's outer top may not be higher than the top of its containing block. When the float occurs between two collapsing margins, the float is positioned as if it had an otherwise empty anonymous block parent taking part in the flow. The position of such a parent is defined by the rules in the section on margin collapsing.
  4. The outer top of a floating box may not be higher than the outer top of any block or floated box generated by an element earlier in the source document.
  5. The outer top of an element's floating box may not be higher than the top of any line-box containing a box generated by an element earlier in the source document.
  6. A left-floating box that has another left-floating box to its left may not have its right outer edge to the right of its containing block's right edge. (Loosely: a left float may not stick out at the right edge, unless it is already as far to the left as possible.) An analogous rule holds for right-floating elements.
  7. A floating box must be placed as high as possible.
  8. A left-floating box must be put as far to the left as possible, a right-floating box as far to the right as possible. A higher position is preferred over one that is further to the left/right.

但在CSS2.1中,如果,在一个块格式化上下文中,存在一个流内拥有垂直方向margin为负值的元素,那么浮动元素的位置在它原本的那个位置的之上,就是所有这些负margin的元素设置成0的时候的位置,浮动元素的位置是未定义的。

ut in CSS 2.1, if, within the block formatting context, there is an in-flow negative vertical margin such that the float's position is above the position it would be at were all such negative margins set to zero, the position of the float is undefined.

后半句啥意思?

在这些规则中其他元素的说明只适用于在相同块格式化上下文中浮动的元素。

References to other elements in these rules refer only to other elements in the same block formatting context as the float.

这个HTML片段的结果是b浮动到右边。

This HTML fragment results in the b floating to the right.

<P>a<SPAN style="float: right">b</SPAN></P>

如果p元素足够宽,a和b将并排,看起来就像这样:

If the P element's width is enough, the a and the b will be side by side. It might look like this:

浮动

9.5.2 紧邻浮动元素的控制流:“clear”属性

“clear”

Value: none | left | right | both | inherit

Initial: none

Applies to: block-level elements

Inherited: no

Percentages: N/A

Media: visual

Computed value: as specified

这个属性指明了一个元素的盒子的哪一边不和更早的浮动盒子相邻。“clear”属性不考虑在元素自身内部或者在其它块格式化上下文中的浮动元素。

This property indicates which sides of an element's box(es) may not be adjacent to an earlier floating box. The 'clear' property does not consider floats inside the element itself or in other block formatting contexts.

当将下面的值应用于非浮动块级盒的时候它们的含义如下:

Values have the following meanings when applied to non-floating block-level boxes:

left 要求盒子的上边框边缘在任何源文档中比这个盒子早的元素引起的左浮盒的外底部边缘的下面。

Requires that the top border edge of the box be below the bottom outer edge of any left-floating boxes that resulted from elements earlier in the source document.

right 要求盒子的上边框边缘在任何源文档中比这个盒子早的元素引起的右浮盒的外底部边缘的下面。

Requires that the top border edge of the box be below the bottom outer edge of any right-floating boxes that resulted from elements earlier in the source document.

both 要求盒子的上边框边缘在任何原文档中比这个盒子早的元素引起的左浮或者右浮盒子的外底部边缘下面。

Requires that the top border edge of the box be below the bottom outer edge of any right-floating and left-floating boxes that resulted from elements earlier in the source document.

none 对盒子与浮动元素相关的位置没有做约束。

No constraint on the box's position with respect to floats.

除“none”外的值潜在的引入了间隙。间隙阻止margin折叠并且承担了一个元素的上margin上面的空间的角色。它被用来垂直推动元素超过浮动元素。

Values other than 'none' potentially introduce clearance. Clearance inhibits margin collapsing and acts as spacing above the margin-top of an element. It is used to push the element vertically past the float.

一个“clear”元素被设置的间隙可以通过先确定元素上边框边缘的假定位置,即元素的“clear”属性被设置为“none”时的上外边框边缘来计算。

Computing the clearance of an element on which 'clear' is set is done by first determining the hypothetical position of the element's top border edge. This position is where the actual top border edge would have been if the element's 'clear' property had been 'none'.

如果这个元素的上边框边缘的这个假定位置没有超过相关的浮动元素,那么间隙被引入,而且margin折叠依据8.3.1的规则实行。

If this hypothetical position of the element's top border edge is not past the relevant floats, then clearance is introduced, and margins collapse according to the rules in 8.3.1.

然后间隙的总大小被设置成下面描述中最大的那个:

  1. 总大小必须至少将被清除的最低的那个浮动元素的外底部边缘作为盒子的边框边缘。

  2. 总大小必须把块上边框边缘放在它的假定位置中。

Then the amount of clearance is set to the greater of:

  1. The amount necessary to place the border edge of the block even with the bottom outer edge of the lowest float that is to be cleared.
  2. The amount necessary to place the top border edge of the block at its hypothetical position.

作为一种选择,间隙精确的被设置到总大小必须把块的边框边缘放置在被清除的最低的那个浮动元素的外底部边缘下面。

Alternatively, clearance is set exactly to the amount necessary to place the border edge of the block even with the bottom outer edge of the lowest float that is to be cleared.

注意:两种行为都允许对存在的web内容的兼容性进行不定求值(pending evaluation)。未来的CSS规范将要求是其中的一种或者另外一种。

Note: Both behaviors are allowed pending evaluation of their compatibility with existing Web content. A future CSS specification will require either one or the other.

注意:间隙可以是负值或者0。

Note: The clearance can be negative or zero.

例子1。假设(为了简单),我们只有三个盒子,按这个顺序:块B1拥有底部margin M1(B1没有子节点并且没有padding或者border),浮动块F拥有一个高度H,块B2拥有一个顶部margin M2(没有padding或者border,没有子节点)。B2有“clear”的值为“both”。我们也假设B2不是空的。

Example 1. Assume (for the sake of simplicity), that we have just three boxes, in this order: block B1 with a bottom margin of M1 (B1 has no children and no padding or border), floating block F with a height H, and block B2 with a top margin of M2 (no padding or border, no children). B2 has 'clear' set to 'both'. We also assume B2 is not empty.

不考虑在B2上的“clear”属性,我们有下面图形所示的情况。B1的margin和B2的margin折叠。假设B1的底边框边缘的位置是y = 0,那么F的顶部在y = M1处,B2的上边框边缘在y = max(M1, M2)处,而F的底部在y=M1 + H处。

Without considering the 'clear' property on B2, we have the situation in the diagram below. The margins of B1 and B2 collapse. Let's say the bottom border edge of B1 is at y = 0, then the top of F is at y = M1, the top border edge of B2 is at y = max(M1,M2), and the bottom of F is at y = M1 + H.

clear属性

我们再假设B2的位置不在F的下面。也就是,我们存在一个情形描述我们必须添加间隙。意思是:

We also assume that B2 is not below F, i.e., we are in the situation described in the spec where we need to add clearance. That means:

max(M1, M2) < M1 + H

我们需要计算间隙C两次,C1跟C2,并且保持两个中较大的那个:C = max(C1, C2)。

We need to compute clearance C twice, C1 and C2, and keep the greater of the two: C = max(C1,C2). The first way is to put the top of B2 flush with the bottom of F, i.e., at y = M1 + H. That means, because the margins no longer collapse with a clearance between them:

第一次是把B2的顶部放到F的底部。例如,在y = M1 + H的地方。就是说,因为它们之间的间隙,margin不再折叠:

The second computation is to keep the top of B2 where it is, i.e., at y = max(M1,M2). That means:

F的底部 = B2的上边框边缘 
M1 + H = M1 + C1 + M2 
C1     = M1 + H - M1 - M2 = H - M2

第二次计算是保持B2的顶部在它所在的地方,例如,在y = max(M1, M2)处。意思是:

We assumed that max(M1,M2) < M1 + H, which implies

max(M1, M2)	= M1 + C2 + M2	
C2	        = max(M1, M2) - M1 - M2

我们假设max(M1, M2) < M1 + H, 说明

We assumed that max(M1,M2) < M1 + H, which implies

C2 = max(M1, M2) - M1 - M2 < M1 + H - M1 - M2 = H - M2	
C2 < H - M2

而,因为C1 = H - M2, 那么

And, as C1 = H - M2, it follows that

C2 < C1

因此

and hence

C = max(C1, C2) = C1

例子2。这是一个负间隙的例子,间隙是-1em。(假设元素都没有border或者padding):

Example 2. An example of negative clearance is this situation, in which the clearance is -1em. (Assume none of the elements have borders or padding):

<p style="margin-bottom: 4em">
  First paragraph.

<p style="float: left; height: 2em; margin: 0">
  Floating paragraph.

<p style="clear: left; margin-top: 3em">
  Last paragraph.

解释:不使用“clear”,第一个和最后一个段落的margin将折叠而且最后一个段落的上边框边缘将被浮动段落冲刷。但“clear”要求上边框边缘在浮动元素的下面,例如,低2em。这意味着间隙必须引入。于是,margin不在折叠并且间隙的总和被设置以保证间隙+margin-top = 2em,就是,间隙 = 2em - margin-top = 2em - 3em = -1em。

译注:可能像这样的情况

Explanation: Without the 'clear', the first and last paragraphs' margins would collapse and the last paragraph's top border edge would be flush with the top of the floating paragraph. But the 'clear' requires the top border edge to be below the float, i.e., 2em lower. This means that clearance must be introduced. Accordingly, the margins no longer collapse and the amount of clearance is set so that clearance + margin-top = 2em, i.e., clearance = 2em - margin-top = 2em - 3em = -1em.

当这个属性被设置到浮动元素时,它导致浮动定位规则的一个变更。一个额外的约束(#10)被添加进来:

  • 浮动的外顶部边缘必须在所有比它早的左浮盒子的外底部边缘的下方(“clear:left”的情况),或者所有比它早的右浮盒的下方(“clear:right”的情况),或者两中情况(“clear:both”)。

When the property is set on floating elements, it results in a modification of the rules for positioning the float. An extra constraint (#10) is added:

  • The top outer edge of the float must be below the bottom outer edge of all earlier left-floating boxes (in the case of 'clear: left'), or all earlier right-floating boxes (in the case of 'clear: right'), or both ('clear: both').

注意:这个属性应用在CSS1中的所有元素。 实现可以在所有元素上支持该属性。在CSS2和CSS2.1中,“clear”属性只能应用在块级元素中。因此作者应该只在块级元素中应用这个属性。如果一个实现支持在行内元素中使用clear,而不按照上面描述的设置一个间隙,这个实现应该强制一个断行并且有效地插入一个或者更多个空的line box(或者像在9.5节中描述的那样向下变动新的line box)用于移动设置了清除的行内的line box的顶部到相关的浮动元素下面。

Note. This property applied to all elements in CSS1. Implementations may therefore have supported this property on all elements. In CSS2 and CSS 2.1 the 'clear' property only applies to block-level elements. Therefore authors should only use this property on block-level elements. If an implementation does support clear on inline elements, rather than setting a clearance as explained above, the implementation should force a break and effectively insert one or more empty line boxes (or shifting the new line box downward as described in section 9.5) to move the top of the cleared inline's line box to below the respective floating box(es).

⚠️ **GitHub.com Fallback** ⚠️