CSS学习8(浮动和定位)
浮动
CSS允许浮动任何元素。
浮动元素
首先,会以某种方式将浮动元素从文档的正常流中删除,不过它还是会影响布局。一个元素浮动时,其他内容会“环绕”该元素。
浮动元素的外边距不会与其他元素的外边距合并。
浮动的详细内幕
包含块,浮动元素的包含块是其最近的块级祖先元素。
浮动元素会生成一个块级框,不论元素本身是什么。它会像块级元素一样摆放和表现。对浮动元素声明 display: block也不是不可能,不过没有必要这么做。
浮动元素要遵守的规则:
- 浮动元素的左(或右)外边界不能超出其包含块的左(或右)内边界。
- 浮动元素的左(或右)外边界必须是源文档中之前出现的左浮动(或右浮动)元素的右(左)外边界,除非后出现浮动元素的顶端在先出现浮动元素的底端下面。这条规则可以防止浮动元素彼此“覆盖”。如果一个元素向左浮动,而另一个元素已经在那个位置,后放置的元素将挨着前一个浮动元素的右外边界放置。不过,如果一个浮动元素的顶端在所有之前浮动图像(元素)的底端下面,它可以一直浮动到父元素的左内边界。
- 左浮动元素的右外边界不会在其右边右浮动元素的左外边界的右边。一个右浮动元素的左外边界不会在其左边任何左浮动元素的右外边界的左边。 这条规则可以防止浮动元素相互重叠。如果宽度不够,它会要求第二个图像向下浮动,直到其顶端在左浮动图像的底端之 下。
- 一个浮动元素的顶端不能比其父元素的内顶端更高。
- 如果一个浮动元素在两个正常元素块之间,放置这个浮动元素时就好像在两个元素之间有一个块级父元素。这个浮动元素浮动在块级父元素中。这样防止浮动元素的顶端超过上面那个元素的底端。
- 浮动元素的顶端不能比之前所有浮动元素或块级元素的顶端更高。
- 如果源文档中一个浮动元素之前出现另一个元素,浮动元素的顶端不能比包含该元素所生成框的任何行框的顶端更高。这个规则进一步限制了元素的向上浮动,不允许元素浮动到包含该浮动元素之前内容的行的顶端之上。假设一个段落的正中间有一个浮动图像。这个图像顶端最高只能放在该图像所在行框的顶端。
- 左(或右)浮动元素的左边(右边)有另一个浮动元素,前者的右外边界不能在其包含块的右(左)边界的右边(左边) 。也就是说,浮动元素不能超出其包含元素的边界,除非它太宽,本身都无法放下,这就能防止出现以下情况,即多个浮动元素出现在一个水平 行上,远远超出其包含块的边界,相反,如果浮动元素出现在另一个浮动元素的旁边,而因此可能导致超出包含块的话,实际上这个浮动元素 会向下浮动到之前浮动元素下面的某一点。
- 浮动元素必须尽可能高地放置。
- 左浮动元素必须向左尽可能远,右浮动元素则必须向右尽可能远。位置越高,就会向右或向左浮动得越远。
实用行为
当父元素的高度比其中的浮动元素小的时候,会发生什么呢。
下面这个例子:
<div id="float1">
不够高的div里有个高高的浮动元素
<div></div>
</div>
<h3>这个标题也会受到冲出来的浮动div的影响</h3>
#float1{
background-color: #1f7e9a;
color:yellowgreen;
//overflow: hidden;
//float:left;
div{
float:left;
width:20px;
height:200px;
margin-left: 30px;
background-color: #ac2925;
}
}
#float1 + h3 {
background-color: #b06d0f;
color: #2aabd2;
}
这时里面的div会冲出父级div向下延伸。下面的元素也会受到影响。这里的h3,虽然总长度还是会填满它的父级div,但是其中的内容却被向右挤了。这是由于浮动元素同时存在于流内和流外,对流内的元素还是有一定的影响,影响的大原则就是使各个元素的内容不互相覆盖。
这个情况看起来特殊其实很普遍,很多时候一个div里全是浮动的元素,那么这个div的高度其实是0,也就意味着这个div下面的元素一定会受到浮动元素的影响。
有两种方法使不够高的父元素来变高包裹住浮动的子元素。就是分别把上面的两句注释取消掉。
第一个会完美的结束浮动,div包裹住所有浮动的元素,以后的元素不会受到影响。
第二个是一个规则,是CSS2.1澄清的浮动元素行为的一个方面:浮动元素会延伸,从而包含其所有后代浮动元素。
负外边距
负外边距可以让浮动元素显示在父元素的外面,看起来违反了上面的规则,其实并没有。
这里就出现了一个问题,如果你将元素的上外边距负的很大,那就意味着一定会影响到已经显示完成的元素们。CSS1和2都明确规定,这里并不需要重绘已经绘制好的元素们。一般用户代理的处理方式都是直接将浮动的div绘制在之前已经显示了的元素的下面。
浮动元素比父元素更宽
在这种情况下,浮动元素会超出右或左内边界,从而尽可能正确地显示,究竞是超出右内边界还是左内边界,取决于元素以何种方式浮动。
浮动元素,内容和重叠
如果一个浮动元素与正常流中的内容发生重叠会怎样呢?
例如,如果一个浮动元素在内容流过的边上有负外边距(例如,右浮动元素上的左外边距为负)就会发生这种情况。
CSS2.1明确了如下规则:
- 行内框与一个浮动元素重叠时,其边框、背景和内容都在该浮动元素“之上”显示
- 块框与一个浮动元素重叠时,其边框和背景在该浮动元素“之下”显示,而内容在浮动元素“之上”显示
- 重叠与元素出现在文档中的顺序无关
以上这些在下面这个例子里都有体现:
<div id="float1">
不够高的div里有个高高的浮动元素
<div></div>
</div>
<h3>这个标题也会受到冲出来的浮动div的影响,块级元素与行内元素重合时</h3>
<span>行内元素与浮动元素重合时</span>
#float1{
background-color: #1f7e9a;
color:yellowgreen;
//overflow: hidden;
//float:left;
div{
float:left;
width:150px;
height:200px;
margin-left: 30px;
margin-top:-10px;
margin-right:-10px;
background-color: #ac2925;
}
}
#float1 + h3 {
background-color: #b06d0f;
color: #2aabd2;
}
#float1 + h3 + span {
background-color: #b06d0f;
color: #2aabd2;
border: 2px dashed #ac2925;
}
清除
你可能并不总是希望内容流过浮动元素,某些情况下,可能要特意避免这种行为。
如果你的文档分组为小节,可能不希望一个小节的浮动元素浮动到另一个小节中。在这种情况下,你希望将每小节的第一个元素设置为禁止浮动元素出现在它旁边。如果这个小节的第一个元素可能放在一个浮动元素旁边,则会将这个元素向下推,直到出现在浮动元素的下面,而且所有后续内容都
在其后面出现。这样就消除了任何浮动元素对这个元素的影响。
在某个元素上使用clear属性可以做到这一点,left | right | both | none | inherit。
这个属性只能应用于块级元素。
在CSS1和CSS2中,clear工作如下,它会增加元素的上外边距,使之最后落在浮动元素的下面,这实际上会忽略为清除元素顶端设置的外边距宽度。会被改成是将元素下移足够远(使内容区在浮动元素下边界的下面)所需的任何长度。
在CSS2.1中,引入了一个清除区域。清除区域是在元素上外边距之上增加的额外间隔,不允许任何浮动元素进入这个范围内。这意味着元素设置clear属性时,它的外边距并不改变。之所以会向下移是这个清除区域造成的。
这里会有两种情况,一种是你的上外边距本身就很大,已经让你的元素在浮动元素之下了,那你的元素是不会受到浮动元素的影响的,clear这时无关紧要。
另一种是你的上外边距并不够大,那clear就会增加这个额外的区域,直到你的元素刚好不被浮动元素影响,这时你的元素刚好在浮动元素的下面,你的上外边距其实起不到什么作用。
你要是希望你的元素清除浮动后能确定的与浮动元素至少有多少距离,就在浮动元素的下面加下外边距吧,这样浮动框大小本身就增加了,clear会把这点考虑进去。
定位
定位的类型
通过position属性可以选择4种不同类型的定位,这会影响元素框生成的方式。
static | relative | absolute | fixed | inherit
默认值为static。可应用于所有元素。
static
元素框正常生成:块级元素生成一个矩形框,作为文档流的一部分,行内元素则会创建一个或多个行框,置于其父元素中。
relative
元素框可以偏移某个距离。元素仍保持其未定位前的形状,它原本所占的空间仍保留。
absolute
元素框从文档流完全删除,并相对于其包含块定位,包含块可能是文档中的另一个元素或者是初始包含块,后面另说。元素原先在正常文档流中所占的空间会关闭,就好像该元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。
fixed
元素框的表现类似于将position设置为absolute,不过其包含块是视窗本身。
包含块
还记得之前浮动元素的包含块嘛,对于浮动元素,其包含块定义为最近的块级祖先元素。
定位的情况稍微复杂些:
- “根元素”的包含块(也称为初始包含块)由用户代理建立,在HTML中,根元素就是html元素,不过有些浏览器会使用body作为根元素。在大多数浏览器中,初始包含块是一个视窗大小的矩形。
- 对于一个非根元素,如果其position值是relative或static,包含块则由最近的块级框、表单元格或行内块祖先框的内容边界构成。
- 对于一个非根元素,如果其position值是absolute,包含块设置为最近的position值不是static的祖先元素(可以是任何类型)。这个过程如下:
如果这个祖先是块级元素,包含块则设置为该元素的内边距边界,换句话说,就是由边框界定的区域。 如果这个祖先是行内元素,包含块则设置为该祖先元素的内容边界。 如果没有符合条件的祖先,元素的包含块定义为初始包含块。
偏移属性
偏移属性来描述定位元素的外边距边界相对于其包含块的偏移。
top、right、bottom、left
可能的值有:(length)| (percentage) | auto | inherit
除了position为static的元素不能使用,其他的都会有效果。
其中百分数值是相对于包含块的高度或宽度来说的。
它们可以是负值,会把元素定位在内容框外。
宽度和高度
尽管有时设置一个元素的宽度和高度很重要,但对于定位元素来说则不一定必要。如果使用top、right、bottom和left来描述元素4个边的放置位置,那么元素的高度和宽度将由这些偏移隐含确定。
可以限制宽度和高度,使用min-width、min-height、max-width、max-height。这两个属性可应用于除了非替换行内元素和表元素以外的所有元素。
绝对定位
这里介绍绝对定位的一些细节。
包含块和绝对定位元素
元素绝对定位时,会从文档流中完全删除。然后相对于其包含块定位,其边界根据偏移属性(top、left等)放置,定位元素不会流入其他元素的内容,反之亦然。这说明,绝对定位元素可能覆盖其他元素,或者被其他元素覆盖。
绝对定位元素的放置和大小
如果一个元素使用4个偏移属性来定位会发生什么 情况?浏览器会根据包含块的大小和定位元素的偏移量来自动计算元素的宽高。但是这样做之后,再试图设置一个显式的高度和宽度会怎么样呢?
这些值可能是冲突的,那就意味着至少一个值会被忽略。right和bottom会被首先忽略,一般这就够了。
自动边偏移
在将某个(除bottom)任意的偏移量设置为auto时,定位元素会相对于其未定位前本来的位置放置,也就是元素在正常流中原本的位置(假设元素“position”属性为“static”时元素的位置)。
不过要注意的是,这时元素已经被从文档流中删掉了,虽然它会被定位到原来的位置,但是会影响后面元素的布局。
非替换元素的放置和大小
考虑一个定位元素的宽度和水平放置。这可以表示为一个等式: left+margin-left+border-left-width+padding-left+width+padding-right+border-right- width+margin-right+right=包含块的width。
在设置的规则不够强的时候,会根据一些规则计算剩下的值。
- 如果left、width和right都设置为auto:左边界会置于其静态位置。元素的width设置为“收放得正好合适”,这说明该元素的内容区宽度恰好只能包含其内容而没有多余空间。
- 左右外边距都设置为auto,而left、width和right不是auto:左右外边距会设置为相等的值。
- 如果只有一个值为auto则会自动计算这个值
- 如果规则相互冲突,重设right
例子:
<div style="position: relative; width: 25em; border: 1px dotted;">
An absolutely positioned element can have its content
<span style="position: absolute; top: 0; left: 0; right: auto; width:auto; background: silver;">
shrink-wrapped
</span>
thanks to the way positioning rules work.
</div>
<div style="position: relative; width: 25em; border: 1px dotted;">
An absolutely positioned element can have its content
<span style="position: absolute; top: 0; left: 3em; right: 1em; width: 10em; margin: 0 auto; background: silver;">
shrinkwrapped
</span>
thanks to the way positioning rules work.
</div>
<div style="position: relative; width: 25em; border: 1px dotted;">
An absolutely positioned element can have its content
<span style="position: absolute; top: 0; left: 1em; right: 1em; width: 10em; margin-left: 1em; margin-right: 1em; background: silver;">
shrink-wrapped
</span>
thanks Co the way positioning rules work.
</div>
垂直情况下情况大致相同,这里有个不错的特点,就是外边距的auto可以用来垂直居中了。不过这种方法只针对height固定的元素有效。
<div id="position-absu-vertical">
<div>This is paragraph text</div>
</div>
#position-absu-vertical{
height:200px;
position: relative;
background-color: #000;
div{
position: absolute;
top:0;
bottom:0;
left:0;
right:0;
margin: auto auto;
height: 50px;
width:50px;
background-color: #fff;
}
}
替换元素的放置和大小
替换元素固有高度和宽度,除非创作人员显式的修改,否则大小不会改变。
在高度或宽度未给定或为auto时,就会自动使用使用替换元素本该有的宽高。
其他的规则基本和非替换元素一样的。
固定定位
固定定位与绝对定位很类似,只不过固定元素的包含块是视窗。固定定位时,元素会完全从文档流中去除,不会有相对于文档中任何部分的位置。
相对定位
如果相对定位一个元素,它会立即为其所有子元素建立一个新的包含块。这个包含块对应于该元素原本所在的位置。设置的偏移量也是针对原本的位置的相对偏移量。当元素相对定位时,它会从其正常位置移走,不过,原来所占的空间并不会因此消失。
如果相对元素的偏移量因为过度受限而发生冲突,则会将一个值会重置为另一个值的相反数。bottom总是等于-top,right总是等于-left。
Z轴上的放置
对于所有定位,最后都不免遇到这样一种情况:两个元素试图放在同一个位置上。显然,其中一个必须盖住另一个。不过,如何控制哪个元素放在“上层”呢?这就引人了属性z-index。
有较高z-index值的元素比z-index值较低的元素离读者更近。这会导致有较高z-index值的元素覆盖其他元素。
所有整数都可以用作为z-index的值,包括负数。如果为元素指定一个负z-index值,会将其移到到离读者更远的位置。也就是说会移到叠放栈的更低层。
—旦为一个元素指定了z-index值,该元素就会建立自己的局部叠放上下文。这意味着,元素的所有后代相对于该祖先元素都有其自己的叠放顺序。这非常类似于元素建立新包含块的方式。比如一个z-index为7的元素的z-index为-1的子元素和一个z-index为6的元素的z-index为10的子元素重叠了。那么是z-index为-1的在上面。
还有一个规则,要求元素绝对不会迭放在其叠放上下文的背景之下。如果一个元素的子元素z-index为负,则会被这个元素的内容覆盖,不被背景覆盖。
元素可见性
visibility:visible | hidden | collapse | inherit
hidden时,这个元素只是不可见了,还是会占用原来它在文档中的位置。这是与display的显著区别。
collapse在表中显示用到的,用于非表元素时collapse与hidden含义相同。
内容溢出
如果一个元素的内容对于元素大小来说过大,就有可能溢出元素本身。对于这种情况,有一些候选解决办法,CSS2允许你从中选择。
当一个元素被固定为某种特定大小,但是元素中的内容过大,就可以使用overflow来控制这种情况。
overflow有这么几个值:visible | hidden | scroll | auto | inherit
可以应用于块级元素和替换元素。默认为visible。
- visible表明,元素的内容在元素框之外也可见。一般地,这会导致内容超出其自己的元素框,但不会改变框的形状。
- 设置为scroll,元素的内容会在元素框的边界处剪裁,溢出的部分将无法直接看到,Web浏览器将使用一个滚动条(或类似的东西)或者使用另外某种方法呈现剩下的内容而不会改变元素本身的形状。要注意的是,如果浏览器采用的是滚动条的实现方式,那么即使元素的大小足够显示其内容,也会出现不可点的滚动条,这是为了防止动态环境中滚动条出现消失而可能带来的布局问题。
- 设置为hidden,元素的内容会在元素框的边界处剪裁,不过不会提供滚动接口使用户访问超出剪裁区域的内容。