Cheshirecat

2 干净的,温暖的


考虑Normal Flow,Position以及Block Formatting Context的关系起因于Kejun在Twitter上所提及的一个在Internet Explorer和Opera下对元素使用绝对定位进行布局时的一个问题,链接在这里:http://hikejun.com/bugs/opera_ie6_overflow_bug.html

检视了一下CSS 2.1文档,Normal Flow,指正常文档流,在W3官方的CSS  2.1文档中并没有直观的表述,而是阐述了它与元素上下文环境的关系:

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

正常文档流中的盒模型属于格式化过的块元素上下文环境或者是行内元素上下文环境,块元素处于块元素上下文环境中,而行内元素则处于行内元素上下文环境中.

对于块元素关系环境,W3在CSS 2.1文档中的解释比较模糊:

Floats, absolutely positioned elements, inline-blocks, table-cells, table-captions, and elements with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts.

浮动元素,使用绝对定位的元素(position属性值为absolute或fixed),另外display属性值为inline-block,table,table-cell,table-caption以及overflow属性值为auto,scroll,hidden的元素可以产生一个新的块元素上下文环境.

而在Mozilla Dveloper Center中有更详细的解释:

A block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with each other.

A block formatting context contains everything inside of the element creating it that is not also inside a descendant element that creates a new block formatting context.

Block formatting contexts are important for the positioning and clearing of floats. The rules for positioning and clearing of floats apply only to things within the same block formatting context. Floats do not affect the layout of things in other block formatting contexts, and clear only clears past floats in the same block formatting context.

所谓的块元素上下文环境是网页样式渲染机制的一部分,它限定了块元素布局区域以及浮动元素相互影响的范围.

现象:正常文档流与元素定位

根据官方文档对于绝对定位,相对定位的解释以及例子,先对使用绝对定位以及相对定位元素与正常文档流的关系做出一个参考性结论.查看例子Example1;从左到右为Example1_N0-Example1_N6.

父级顶层容器(OUTER)通用样式

float:left;margin-right:20px;width:200px;line-height:25px;

父级次层容器(SUB_OUTER)通用样式

background:#eee url(line_mark_1.gif) scroll repeat-x 0 100%;

使用定位方法进行布局的子元素(INNER)样式见页面顶部黑色块状内内容.

Example1_N0为正常文档流,顶部绿色标记线与底部绿色标记线距离为500px;

Example1_N1中INNER使用相对定位,非块状,定位元素原空间空白占位显示,顶部绿色标记线与底部绿色标记线距离为500px;

Example1_N2中INNER使用相对行为,块状显示,定位元素原空间空白占位显示,占位空间为块状化后尺寸,顶部绿色标记线与底部绿色标记线距离为500+2(horiziontal border width)px

Example1_N3中INNER为相对定位,块状显示,高度减少25px,定位元素为块状化后并以最终计算高度以空白空间方式占位,顶部绿色标记线与底部绿色标记线距离为(500-25)+2px;

Example1_N4中INNER为绝对定位,绝对定位元素以块状显示,高度减少25px,定位元素无空白占位空间,顶部绿色标记线与底部绿色标记线之间的距离为500-50px;

Example1_N5中INNER为相对定位,以块状显示,高度减少25px;宽度增加为210px;定位元素为块状化后并以最终计算高度以空白空间方式占位,顶部绿色标记线与底部绿色标记线距离为(500-25)+2px;OUTER与SUB_OUTER可见宽度及内容宽度无变化(与overflow:visibile相关).

Example1_N6中INNER为绝对行为,绝对定位元素以块状显示,高度减少25px;宽度增加为210px;定位元素为块状化后并以最终计算高度以空白空间方式占位,顶部绿色标记线与底部绿色标记线距离为500-50px;OUTER与SUB_OUTER可见宽度及内容宽度无变化(与overflow:visible相关).

根据Example可以得出绝对定位和相对定位元素同正常文档流之间的关系的参考性结论,对于使用相对定位的元素,并未脱离正常文档流,而是相对正常文档流进行了偏移,偏移量受top/bottom,left/right值所限,同时并以元素最终计算尺寸以空白形式占位正常文档流.对于使用绝对定位的元素,从正常文档流中脱离,不占有正常文档流空间.另外还可以得出结论,在默认元素样式属性overflow的值为默认的visible(body的默认值为auto;)的情况下,不对其父及容器产生影响.

现象:正常文档流与块元素上下文环境

从Example1中我们得出使用绝对定位以及相对对元素进行定位后与正常文档流之间的关系,Example2对正常文档流与块元素上下文环境进行简要分析,得出参考性结论.查看例子Example2,从下之下为Example2_N0(_1-6)-Example2_N7.

红色为父级顶层容器(OUTER),通用样式如下:

width:400px;height:400px;background:#f00 url(ruler.gif) no-repeat scroll 0 300px;

绿色为父级次层容器(SUB_OUTER),通用样式如下:

width:500px;height:300px;background:#0f0 url(ruler.gif) no-repeat scroll 0 200px;

蓝色为使用绝对定位的子容器(INNER),通用样式如下:

width:800px;height:200px;background:#00f url(ruler.gif) no-repeat scroll 0 0;

样式差异见表格Example2_N*中的Property列.

Example2_N0,OUTER,SUB_OUTER,INNER存在于由BODY生成的默认块元素上下文环境中,主要作用为对照.在Firefox 2.0(Above),Opera 9(10)中OUTER的scrollWidth,clientWidth均为400px,SUB_OUTER的scrollWidth,clientWidth均为500px,Internet Explorer 6(7),Chrome 2,Safari 4 将OUTER,SUBOUTER的有效内容宽度scrollHeight增加到800px,也就是等于INNER的宽度,而在Internet Explorer 6 中,OUTER,SUB_OUTER的可视宽度clientWidth增加到800px,所以在Internet Explorer 6下OUTER,SUB_OUTER的实际显示的宽度为800px,这应该是Internet Explorer 6一直存在的一个解释上的Bug.

Example2_N1中,由于对SUB_OUTER使用相对定位,会在OUTER的空间中保留占位空间,相当于在OUTER中保留一个样式属性position值为static的SUB_OUTER,所有浏览器都以各自的正常情况显示.从这个例子来看,BODY为原始的块元素上下文环境,而INNER为元素级别的第一个块元素上下文环境,它的作用是将其所包含的子元素与INNTER所在的外部上下文环境所隔离,在本例中无实际作用.

Example2_N2中将SUB_OUTER样式属性overflow设置为auto;可以看到SUB_OUTER出现滚动条,由于SUB_OUTER此时的可视宽度clientWidth为500px,而INNER的scrollWidth有效内容宽度为800px,滚动条可拖动范围为(800-500)px.其他现象同Example2_N1.Example2_N3将SUB_OUTER样式属性overflow设置为hidden,各元素width值与Example2_N2相同,INNER超出SUB_OUTER的宽度被隐藏,值得注意的是,在Example2_N2中,Internet Explorer6(7)滚动条拖动时拖动对象还包含SUB_OUTER自身,而不只是对其包含的子元素,也就是INNER进行拖动.

Example2_N2以及Example2_N3共同点在于样式属性overflow的值均不等于visible.因此SUB_OUTER新建了一个块元素上下文环境,其所包含的子元素INNER便与SUB_OUTER的外部上下文环境相隔离,而此时SUB_OUTER的有效宽度scrollWidth等于INNER的有效宽度,为800px.

在Example2_N4中,将OUTER的样式属性overflow设置为auto,在Example2_N5中将OUTER的样式属性overflow设置为hidden,同理,此时OUTER将会新建一个块元素上下文环境,在Firefox 2.0(Above),Opera 9(10),Chrome 2,Safari 4 中 OUTER的有效内容宽度scrollWidth值为800px,等于INNER的宽度,在Example2_N4中,滚动条的可拖动范围为(800-400)px,包含SUB_OUTER(500-400)px.不过在Internet Explorer 6(7)下OUTER的有效内容宽度scrollWidth值为500px,可视宽度clientWidth的值变为400px,滚动条可拖动范围为(500-400)px,拖动对象为OUTER自身.

Example2_N6与Example2_N4,Example2_N7与Example_N5的区别相同,在OUTER添加了样式属性position,值为relative,而此时Internet Explorer做出与其他浏览器相同的解释,不过对于Example2_N6,Internet Explorer保留了与Example2_N2以及Example2_N4的相同现象,滚动条拖动对象包含自身.

从Example2中我们可以得出一个临时参考性结论,Firefox,Opera,Chrome,Safari当新的块元素上下文环境产生时,可以直接影响其包含的所有子元素,而Internet Explorer则受正常文档流的限制要多.

(未完)