盒模型
CSS假定每个元素都会生成一个或多个矩形框。每个框中心都有一个内容区,这个内容区周围有可选的内边距、边框和外边距。这些项之所以被认为是可选的,原因是它们的宽度可以设置为0。
- 可以用多种属性设置各外边距、边框和内边距。
- 内容的背景也会应用到内边距
- 外边距通常是透明的,从中可以看到父元素的背景
内边距不能是负值,但外边距可以。
边框的颜色如果没有设置,那么将取元素内容的前景色。
- 如果边框样式有某种缝隙,则可以通过这些缝隙看到元素的背景。
- 边框的宽度绝对不能为负。
对于不同类型的元素格式化时存在着差别。块级元素的处理不同于行内元素,而浮动元素和定位元素也分别有各自不同的表现。
包含块
每个元素都相对于其包含块摆放,包含块就是一个元素的布局上下文。
包含块由最近的块级祖先框、表单元格或行内块祖先框的内容边界构成。
<body>
<div>
<p>lalalala</p>
</div>
</body>
在这个例子中,p元素的包含块是div元素,类似的,div的包含块是body元素。
因此,p的布局依赖于div的布局,而div的布局则依赖于body的布局。
重要概念
正常流:
这是指正常西方语言文本从左向右、从上向下显示,这也是我们熟悉的传统HTML文档的文本布局。
大多数元素都在都在正常流中,要让一个元素不在正常流中,唯一的方法就是使之成为浮动或定位元素。非替换元素:
如果元素的内容包含在文档中,则为非替换元素。例如,如果一个段落的文本内容都放在该元素本身之内,这个段落就是一个非替换元素。替换元素:
CSS 里,替换元素(replaced element)的展现不是由CSS来控制的。这些元素是一类外观渲染独立于CSS的外部对象。
典型的可替换元素有<img>、 <object>、 <video>
和 表单元素,如<textarea>、 <input>
。 某些元素只在一些特殊情况下表现为可替换元素,例如<audio> 和 <canvas>
。 通过 CSS content 属性来插入的对象 被称作 匿名可替换元素(anonymous replaced elements)。
CSS在某些情况下会对可替换元素做特殊处理,比如计算外边距和一些auto值。块级元素:
块级元素在正常流中,会在其框之前和之后生成换行,所以处于正常流中的块级元素会垂直摆放。
通过声明display:block,可以让元素生成块级框。行内元素:
行内元素不会再之前和之后换行,它们是块级元素的后代。
通过声明display:inline,可以让元素生成一个行内框。根元素:
位于文档树顶端的元素。在HTML文档中,这就是元素html。
块级元素
一般地,一个元素的width被定义为从左内边界到右内边界的距离。height则是从上内边界到下内边界的距离。这些属性都可以应用到元素。
水平格式化
水平格式化比较复杂,其部分复杂性在于width影响的是内容区的宽度,而不是整个可见的元素框。
因此如果为一个固定宽度的元素指定了内边距、边框或外边距,这些都会增加到宽度值。
<p style="width:200px;padding:10px;margin:20px">lalala</p>
此时整个元素框的宽度为200+10* 2+20*2 =260px。
一定要知道这样会隐式的增加width值。
对此有一个很简单的规则:正常流中块级元素框的水平部分总和就等于父元素的width。
假设一个div中有两个段落,这两个段落的外边距设置为1em。段落的内容宽度再加上其左右内边距、边框或外边距,就正好是div内容区的width。
水平属性
水平格式化的七大属性是:margin-left、margin-right、border-left、border-right、padding-left、padding-right、width。
这七个属性的值加在一起必须是元素包含块的宽度,往往是块元素的父元素的width值。
在这7个属性中,只有3个属性可以设置为auto:
- width
- 左外边距
- 右外边距
其余属性必须设置为特定的值,或者默认宽度为0.
请注意,width属性适用于除非替换或内联元素,表行和行组(即thead,tfoot和tbody)之外的所有元素。
使用auto
如果设置width、margin-left或maigin-right中的某个值为auto,而余下两个属性指定为特定的值,那么设置为auto的属性会确定所需的长度,从而使元素框的总宽度等于父元素的width。
假如7个属性的和必须等于400像素,没有设置内边距或边框,而且右外边距和width设置为100px,左外边距设置为auto。那么左外边距的宽度将是200像素。
从某种程度上讲,可以用auto弥补实际值与所需总和的差距。
要是这三个属性都设置为100px,即没有任何一个属性设置为auto,会怎么样呢?
如果这三个属性都设置为非auto的某个值,此时总会把margin-right强制为auto。
这意味着,如果外边距和width都设置为100px,用户代理将把右边距重置为auto。右外边距的auto值将会填补所需的距离,使元素的总宽度等于其包含块的width。
p {
margin-left:100px;margin-right:100px;width:100px}
/* right margin将被强制变为200px */
对于从左向右的语言会把margin-right设置为auto,但如果是从右到左的语言,一切正相反,所以会把margin-left强制为auto。
如果两个外边距都显式设置,而width设置为auto,width值将设置为所需的某个值,从而达到需要的总宽度。
这等价于只设置外边距而没有为width做任何声明,因为width的默认值就是auto。
不只一个auto
这三个属性中如果有两个都设置为auto会出现什么情况呢。
如果两个外边距都设置为auto,它们会设置为相等的长度,因此将元素在其父元素中居中。
将两个外边距设置为相等的长度是将元素居中的一种正确方法,这不同于使用text-align。(text-align只应用于块级元素的内联元素,所以将元素的text-align设置为center并不能将这个元素居中)将某个外边距以及width设置为auto,设置为auto的外边距会减为0。然后width会被设置为所需的值来使得元素完全填充其包含块。
p {
margin-left:auto; margin-right:100px; width:auto;}
/*left margin evaluates to 0 */
- 如果三个属性值都被设置为auto,两个外边距会设置为0,而width会尽可能宽。
这种情况与默认情况是相同的,即没有为外边距或width显式声明任何值,在这种情况下,外边距默认为0,width默认为auto。
注意,由于水平外边距并不会合并,父元素的内边距、边距和外边距可能影响其子元素的布局。
负外边距
7个水平属性的总和要等于父元素的width,只要所有属性都是大于等于0,元素就不会大于其父元素的内容区。
但是,如果指定了负外边距:
div {
width:400px; }
p {
margin-left: