ivanberry / CSS-Knowledge

记录一些常见的面试题,不仅仅是为了面试,它是一个指导,一个大纲,弥补自己知识的不够
4 stars 0 forks source link

CSS布局学习(一): Normal flow #12

Open ivanberry opened 8 years ago

ivanberry commented 8 years ago

1, 定位

CSS布局就是将一组HTML元素映射成放置在x,y轴上的一系列矩形盒子.而x,y坐标位置是由_定位方式_确定的(positioning scheme).CSS2.1中定义三类不同得定位方式:normal flow, float 还有absolute position.元素位置得确定最先由定位方式确定,一旦定位方式确定,元素位置可由特殊的布局方法修改如: display: table等等.CSS3中更是引入了flexboxgrid.

定位方式(CSS2.1)

文档所有元素都属于normal flow,一旦定义了float或者position属性,就会从normal flow中移除.

normal flow由包含有两方面内容:

包含元素中的子元素的相对位置是由同级子元素格式化环境决定的,在normal flow中可能是_block_或_inline_格式化环境.

Boxes in the normal flow belong to a formatting context, which may be block or inline, but not both simultaneously. Block-level boxes participate in a block formatting context. Inline-level boxes participate in an inline formatting context.Source

块级元素定义:

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

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. Some block-level elements may generate additional boxes in addition to the principal box [for example,]: 'list-item' elements. These additional boxes are placed with respect to the principal box.

几乎所有块级元素都是块级包含容器,它就是一系列其他拥有特定环境得其它盒子.

行级元素定义:

Inline-level elements are those elements of the source document that do not form new blocks of content; the content is distributed in lines (e.g., emphasized pieces of text within a paragraph, inline images, etc.). The following values of the 'display' property make an element inline-level: 'inline', 'inline-table', and 'inline-block'. Inline-level elements generate inline-level boxes, which are boxes that participate in an inline formatting context.

An inline box is one that is both inline-level and whose contents participate in its containing inline formatting context. A non-replaced element with a 'display' value of 'inline' generates an inline box. Inline-level boxes that are not inline boxes (such as replaced inline-level elements, inline-block elements, and inline-table elements) are called atomic inline-level boxes because they participate in their inline formatting context as a single opaque box.

简单粗暴地说: 你可以认为文档流中的竖直叠加(块级格式化环境)和水平叠加(行级格式化环境).

由上述可知,文档流中的元素要么是处于行级格式化环境,要么就是块级格式化换进,没有其它.但是当你混合使用divs和a等时,那是怎么实现的呢?这就需要一个将行级元素变成块级元素的机理:匿名盒子.

匿名盒子

两种情况会产生匿名盒子:

  1. 父容器中混合有块级元素和行级元素
  2. 文字中出现行级元素.
1

<div>
<span>inline-level element</span>
<p>block level element</p>
</div>
2
<p>some text<em>inline-level element</em>some text</p>

匿名块级盒子:

  1. 若块级包含盒子中只包含有块级元素,那么它内部只会产生匿名块级盒子.
<div>
        some text
        <p>more texts</p>

匿名盒子

块级匿名盒子还会产生一些少见得情况中:

When an inline box contains an in-flow block-level box, the inline box (and its inline ancestors within the same line box) are broken around the block-level box (and any block-level siblings that are consecutive or separated only by collapsible whitespace and/or out-of-flow elements), splitting the inline box into two boxes (even if either side is empty), one on each side of the block-level box(es). The line boxes before the break and after the break are enclosed in anonymous block boxes, and the block-level box becomes a sibling of those anonymous boxes. When such an inline box is affected by relative positioning, any resulting translation also affects the block-level box contained in the inline box.

匿名行级盒子:

当块级包含元素包含有未包含在行级元素内的文字时会产生匿名行级元素:

<p>some <em>emphasized</em> text</p>

匿名盒子的存在非常重要,它决定文档流中毗邻得块级元素和行级元素之间得布局,当块级元素和行级元素毗邻存在时,行级元素会假装自己包裹在一个匿名块级元素当中.

文档流中得布局由上述得两种格式化环境确定,在表现上,它们可以简单地认为是竖直叠加和水平叠加

竖直叠加

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

简单总结就是: 块级格式化环境中,盒子的布局在竖直方向一个接着一个排布,竖直距离由margin决定,当然相邻块级元素间的竖直外边距会合并(不是相加,而是表现为大的外边距).块级元素中重要的两点:

  1. 竖直排布
  2. 盒子左外边缘靠近包含块级元素的左外边缘
.float {
  float: left;
}
.foo {
  padding-top: 10px;
}
.bar {
  width: 30%;
}
.baz {
  width: 40%;
}
<div class="container violet">
  <div class="float red">float</div>
  <div class="foo blue">foo</div>
  <div class="bar green">bar</div>
  <div class="baz orange">baz</div>
</div>

例子

上述例子中:

块级格式化环境总体而言是很简单的,但是行级格式化环境就相对而言复杂了.

normal flow: 行级块级格式化环境

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.

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-height决定.

行级格式化环境中的对齐可能才是难点所在:

行级格式化环境中得水平对齐

首先需要明确,只有当行盒子中还有未利用空间时,属性定义才会有意义.标准中提到:

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

行级格式化环境的竖直对齐

vertical-height决定行盒中行内盒子的对齐.为了了解竖直对齐,首先要知道行内盒子和行盒子高度是怎么来的.

行盒高度:

The 'height' property does not apply. The height of the content area should be based on the font, but this specification does not specify how. A UA may, e.g., use the em-box or the maximum ascender and descender of the font. [...]

The vertical padding, border and margin of an inline, non-replaced box start at the top and bottom of the content area, and has nothing to do with the 'line-height'. But only the 'line-height' is used when calculating the height of the line box.

简单说来: 行内元素得高度由字体高度*line-height值决定.

还有好多细节,我们先不深究,待议

文档流:相对位置

position: relative被认为normal flow的一部分.

relative: The box's position is calculated according to the normal flow [...]. Then the box is offset relative to its normal position. When a box B is relatively positioned, the position of the following box is calculated as though B were not offset. The effect of 'position:relative' on table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption elements is undefined.

也就是说: 相对定位的元素和未定义position属性得元素一样,只不过能通过top, left,right, bottom来偏移.

.float {
  float: left;
}
.foo {
  padding-top: 10px;
}
.bar {
  position: relative;
  top: -20px;
  left: 10px;
  width: 30%;
}
.baz {
  width: 40%;
}
<div>
<div class="float red">float</div>
<div class="foo blue">foo</div>
<div class="bar green">bar</div>
<div class="baz orange">baz</div>
</div>

例子0

ivanberry commented 8 years ago

“相对定位”

.bar向上移动20px,但是.baz依旧还是当作它在原来的地方,这很好的证明了relative的元素是_normal flow_的一员。

ivanberry commented 8 years ago

Absolute/fixed positioning scheme

绝对定位是最后一种定位方案,它们很容易理解,绝对定位元素对布局其他元素而言,基本是不影响的,从根本上是做到了“人畜无害”。甚至她们中的浮动元素也不会影响到父元素外的其他元素。绝对定位有两类,区别在”绝对“的参考不同:

spe中是这么描述的:

absolute: The box's position (and possibly size) is specified with the 'top', 'right', 'bottom', and 'left' properties. These properties specify offsets with respect to the box's containing block. Absolutely positioned boxes are taken out of the normal flow. This means they have no impact on the layout of later siblings. Also, though absolutely positioned boxes have margins, they do not collapse with any other margins.

fixed: The box's position is calculated according to the 'absolute' model, but in addition, the box is fixed with respect to some reference.