css布局定位系列 (转)

 

英文原文地址:http://brainjar.com/css/positioning/default.asp

翻译:零度,转载请注明本文英文原文出处以及本文地址!由于我英文水平有限,有不懂的地方还请阅读原文,欢迎交流!

CSS 定位

理解怎么布局页面内容有助于我们更好的利用css布局。这篇文章给了CSS2 规范里的一些方法和规则。它同时指出了一些我们需要留神的东西。

尽管规范适用于任何网页展示设备,这篇文章只集中考虑它是怎么在浏览器里工作的。为了简单,我们忽略了许多细节。想要更精确的参考,请阅读标准文档。

记住一个特定的浏览器不支持某些特性或者不会正确执行这个特性是很重要的。同时,某些浏览器除了支持标准,它们还有会有少许的偏离,这些差异是需要我们注意的。

盒子模型

为了理解CSS定位,你必须首先理解盒子模型。为了显示,文档里的每一个元素被认为是一个矩形盒子,这个盒子有一个内容域,内容域被padding、border和margin包围.下面的插图展示了各个不同的部分。

content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content

    margin     border     padding     content

Margin总是透明的。Border可以有不同的风格。为一个元素设置背景样式将被应用到border里的padding和内容域。为了能让你看得更清晰,上面的padding域有一个很浅的灰暗背景。

当这篇文章涉及到盒子的时候,术语"margin edge"、"border edge"(margin边、bodder边)等指的是和上面盒子相似的外边缘!

marging、border和padding都是可选的(可有可无的),为了计算位置和大小,如果没有特别说明,它们有一个默认值零。如果需要,每一条可见边都可以有不同的宽度(这里指border的四条边,因为只有border可见,译者注)。Margin甚至可以有负值!

每一个盒子的宽度和高度等于margin外沿的宽度和高度。请注意盒子的大小并不总是内容域的大小(可以是)。

一个盒子可以包含任何数目的其他盒子,新增一个具有层次的盒子和插入一个页面元素等价。浏览器窗口是所有层次的根元素。

盒子类型

盒子有两种基本类型:block(块级)和inline(行内,国内有时也译为内联元素,意思一样)。块级盒子由P、DIV或者TABLE等元素生成。行内盒子由B、I或者SPAN等标记以及内容文本和图片组成。

盒子的类型可以通过diplay属性改变。比如给一个行内元素设定一个block值就可以使这个元素具有块级元素的特征。注意,如果你把display的属性设为none,这个盒子是不会产生的,它不会被浏览器显示,同样的,这个盒子里的任何元素都会被浏览器忽略,不管它们是否被声明为其他的属性!

一些特殊的元素比如list和table还有其他的盒类型。然而,如果是为了定位,这些元素的其他盒类型也会当作block或者inline看待,这里就不考虑了。


包含块

对一个块级盒里的所有元素来说,这个块级盒可以看成它们的包含块。例如以下代码:

<div>
This is the first sentence.
<p>This is the second sentence.</p>
</div>

这个div元素就为第一行文本和下面的P元素建立了一个包含块。P元素又为它里头的文本建立了另外一个包含块。

注意到上面例子中的第一行文本产生了一个行类盒是很有意思的,在这里认为下面的块级盒围绕在它的周围。像这样的匿名块级盒被用来简化定位处理。结果就是这样的一个块级盒将只能包含行内盒,或者只能包含块级盒,甚至有些这样的块级盒只能围绕在行内盒的周围。

包含块用来计算它里头元素盒的位置以及范围。比如,如果一个元素的样式是{50%},它的宽度将被设置为包含块的一半。

对于任何一个没有绝对定位的元素,它的包含块被认为是父级块中内容边沿与它最接近的块级盒。如果不存在这样的一个父级盒,那么它的块级盒就是浏览器窗口。我们分开考虑绝对定位元素。

定位模式

CSS2里有3种定位模式:normal,float和absolute。每一种类型都有自己独立的规则。每一个盒子只能使用这三种类型中的一种,不同盒子根据它们自己的定位和浮动样式设置选择不同的模型。

正常流(Normal Flow)


正常流是默认的定位方式。任何没有具体指定{position:absolute}或者{position:fixed}属性以及没有被浮动的元素都将默认获得此属性。

在这种方式里,块级盒在它们的包含块里一个一个垂直延伸,行内盒在它们的包含块里从左至右的水平排布。

你应该注意到在正常流里垂直边距(vertical margin)是重叠的。也就是说,上下两个块级盒之间的边距由它们之中边距较大的元素决定,而不是他们的和!下面图示说明了这一点。

content content content content content content content content content
content content content content content content content content content content content content content content content content content content

当然,在水平方向上,块级元素的边距从来不会重叠。


如果需要,行内块是可以被折断的,当宽度受到限制的时候,它会自动移动到下一行。这可能会产生一些难看的效果如果行内块有边框的话。看下面的效果:

content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content

按照标准,上面两条边线的相交只应该显示三条边。



相对定位

当一个元素被指明为{position:relative;}的时候,它开始是遵守正常流规则的(也就是说,如果你不给他任何规则,他就和正常的一样,译者注),它周围元素相应的被定位。然后,元素盒根据它的属性值偏移。

content content content content content content content content content
content content content content content content content content content
content content content content content content content content content

 

请注意上面元素周围的盒子是正常布局的,包括垂直边距的折叠,因此,采用相对定位的元素有可能覆盖其他元素。

浏览器兼容性

浏览器在处理相对定位元素覆盖其他元素的方法上是存在分歧的。不幸的是,W3C标准并没有指明应该怎么处理这个问题。

因此,像IE5.5和Netscape6.0,会将相对定位元素显示在他周围元素的上面。而其余的,比如Opera5.0,将使用缺省栈指令,从而是将相对定位元素显示在文档流里比它先出现元素的前面,比它后出现元素的后面。

栈指令在绝对定位参考中有详细的描述。但是请注意你可以使用z-index属性去设定它的显示顺序(z-index的值越大,元素越靠前显示!)

可以联合使用top,right,left和bottom四个属性来设置相对定位元素的偏移值。每一个属性值被解释为元素外边框相对于原来正常位置的距离。

请注意这些偏移值是有约束的。例如,假设你同时设定了left和right属性的值,如果其中一个元素的值不是另外一个值的相反值的话(比如4和-4,译者注),那么right属性的值将会被忽略。设定某一个具体的宽度值也有可能使偏移值被忽略。这个规则同样适用于top,bottom以及height属性。

在实际中,你将很有可能只设定left,right中的任一个以及top,bottom中的任一个。

子节点定位(Descendant Positioning)

相对定位元素是否建立一个新的包含块以定位(相对定位或者绝对定位)子元素是不确定的,他们遵守非定位元素一样的规则。

如果相对定位元素是块级元素,那么它将建立一个新的包含块。在它里面的元素使用元素的偏移量作为基础定位。也就是说,子元素的偏移量是一个复合值(包含块偏移量加上它自己的偏移量)

如果相对定位元素是行类元素,它的偏移量和它的子元素没有关系,相反,它和它的子元素共享同一个父级包含块。

浏览器兼容性

最初的W3C标准声明,相对定位元素总是建立一个包含块。然而,后续标准修正了这个声明,指出相对定位元素和普通元素一样。

有一些浏览器包括了这个修正但是有一些没有。由于这个差别,你可能希望避免这样的情况,总是使用一个块级元素用于相对定位。



 

浮动(Floats)

通过设定一个元素的浮动属性为left或者right就达到了浮动的目的,浮动有一些特殊的规则。

声明浮动后,元素盒在垂直方向上应该处于普通流里面(即元素不会脱离正常文档流,译者注),它的上边线和原来的位置一样,但是在水平方向上,它的一条边尽可能的靠近它的包含块边线,和其他内容一样,浮动元素处于包含块的padding内。它周围的行内元素允许围绕在他的另一边(opposite side)。

下面的插图体现了如下代码的效果,一个浮动元素被定义为部分行类文本(为了简洁,这里忽略了margin,border和padding样式)。

<p>  <span style="float:right;40%;">content...</span>  content content content content content content content content...</p>
content content content content
content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content

浮动的属性值可以设置为left,right,none和inherit中的任一个。

关于浮动元素盒(float box),有几个地方值得注意。

首先,浮动元素盒必须有一个显式的或者隐式宽度。否则,它会在水平方向上填满它所在的包含块,就像其他普通元素一样,不能给它周围的元素腾出空间。这样的话,浮动元素盒就像块级元素一样被对待,就算它被声明为行内元素。

其次,和正常流的元素盒不一样,一个浮动元素盒的垂直边距(vertical margins)不会和它上面或者下面的元素重叠。

最后,在正常流里,一个浮动元素盒能够和它邻近的大块块级元素互相搭接在一起。这里有一个浮动元素比它包含块大很多的例子,为了显示效果,我们不得不在下面增加一个段落。

<p>  <span style="float:right;40%;">    content content content content content content content content    content content content content content content content content...  </span>  content content content content...</p><p>content content content contentcontent content content content...</p>
 
content content content content content content content content content content content content content content content content content content content content content content content content
content content content content content content content content content
content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content

我们可以看到,上面的这个浮动元素盒覆盖了它的父级盒以及它下面元素盒的边框(尽管第二个块级元素盒里的文本围绕在它的周围),我们可以使用清除属性(clear)来避免这样的情况。

给下面的那个块级盒设定clear:right;属性就可以把它移动到浮动元素盒的下面。最后,这里有一个使用类似代码的例子。

<p>  <span style="float:right;40%;">    content content content content content content content content    content content content content content content content content...  </span>  content content content content...</p><p style="clear:right;">content content content contentcontent content content content...</p>
content content content content content content content content content content content content content content content content content content content content content content content content
content content content content content content content content content
content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content

这样就能给浮动元素下面的块级盒的上边距(top margin)增加了足够的空间使得第二个段落的边框和内容恰好在浮动元素盒的下面。

上面浮动元素盒和它的父级盒(父级盒里的文本段落)重叠了,那是因为我为了这个目的而特意在浮动元素盒里添加大量的内容以便和它周围的元素相比较。

通常可以通过将浮动元素放置在段落的外面使两个段落都在它之下而解决问题。

clear属性的值可以设定为left,right,both,none和inherit之一。它只对块级元素有意义。

邻近浮动(Adjacent Floats)

当两个或者两个以上的相邻元素都被浮动的时候,如果存在足够的空间去容纳他们,它们的上边线是在同一水平线上的。如果没有足够的空间,那么后面的浮动元素将会下移到能够容纳它的地方,它总是对准一个线性盒!

应该注意的是这个向下移动的元素有可能产生一个单独的浮动 元素如果它太宽了以至于不能用它的相邻内容填充它的初始位置。

下面的插图显示了两个浮动元素排在一起的效果。请注意第二个浮动元素看起来是怎样距右边最近的(原文内容为:Note how the first floated element appears farthest to the right.
,我认为第二个浮动元素更恰当)。

first float
second float
content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content


给一个浮动元素应用clear属性可以强制它处于相邻浮动元素之下(回忆一下浮动元素可以当作块级元素用于布局)。只是需要记得浮动元素的垂直边距是不会重叠的(不会像块级元素一样,垂直边距有可能被忽略,译者注)。这里有一个代码相同但是第二个浮动元素使用了clear:right样式的例子。

first float
second float
content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content content


绝对定位(Absolute Positioning)

这个定位方案应用于任何position属性被设定为absolute或fixed的元素。

这样的绝对定位元素盒是脱离了普通的文档流的,它在文档流里没有任何效果(就好像不存在一样)。和具有浮动属性的元素一样,绝对定位元素总是被看作块级元素。因此,它为它的所有子元素建立了一个包含块。也就是说,它的所有子元素都处在这个绝对定位盒里面。

一个绝度定位元素的位置决定于它的偏移量:top,right,bottom和left。它们和相对定位元素的偏移量作用一样。

但是和相对定位不同的是,相对定位元素的偏移量是根据它在正常文档流里的位置计算的,而绝对定位是按照它的包含块的位置计算的。

绝对定位元素的包含块

绝对定位元素包含块的定义和其他元素有一点点不同。绝对定位元素的包含块是由距离它最近的已被定位的祖先元素确定的,也就是在它外面最接近它的position属性值为absolute,relative或者fixed的父级元素。如果不存在这样的一个父级元素,那么最原始的包含块(浏览器窗口)就是它的包含块。

回忆一下一个非绝对定位元素是使用距离它最近的父级块元素作为它的包含块的,但是绝对定位元素的包含块可以是一个行内元素。

此外,如果这个包含元素是一个块级元素的话,那么它是由补白边缘(padding edge )而不是内容边缘(content edge)组成的。换句话说,偏移量是从父级包含块元素的边框内开始计算的(the offsets are measured from just inside the border of the containing element.
)。

如果包括块元素是一个行内元素的话,情况变得复杂了点。因为一个行内元素有可能产生好几个线性盒(line boxes),这时包含块被定义为这样的一个区域,它的左边框以及上边框由行内元素包含的第一个元素内容的左边框以及上边框确定,它的下边框以及右边框由它所包含的最后一个元素内容的下边框以及右边框确定(原文:Since an inline element may generate several line boxes, the container box is defined as the area bordered by the top and left content edges of the first box within that element and the bottom and right content edges of the last box it contains.
).

例如,考虑一个包含两行文本的相对定位的span元素,文本中有一单词是粗体的。

content content content content content content
content content

从上面的插图可以看出,它的包含块将会是包含第一行和最后一行的阴影部分。

由于我们先前提到的浏览器处理相对定位元素是有差异的,把一个绝对定位元素插入一个相对定位元素里面同样有可能产生一些不可预料的结果,这值得我们去避免。

注意一下当我们给绝对定位元素设定边距margin时(位置偏移从元素的边距margin开始计算)
是没有任何意义的因为绝对定位元素在普通的文档流里是不存在的
(原文:Note that while margins are honored with absolutely positioned elements (position offsets are measured from the margin edge of the element's box) they are otherwise meaningless since absolutely positioned elements do not participate in the normal flow.)。

一个绝对定位元素为它所包含的任何元素建立了一个包含块。子元素遵守和他们在普通流里一样的规则,只是他们的偏移位置由他们的包含块确定。

他们甚至可以包含其他的绝对定位元素,这些绝对定位子元素同样可以从包含块里的文档流里脱离,所以他们可以出现在包含块边缘的外面。这可以从上面的演示中看到。

 
原文地址:https://www.cnblogs.com/ma/p/639233.html