CSS 盒模型
所有文档元素都生成一个矩形框,这称为元素框(element box),它描述了一个元素在文档布局中所占的空间大小。而且,每个框影响着其他元素框的位置和大小。
网页布局中,我们是如何把里面的文字、图片等内容,按照美工给我们的效果图排列的整齐有序呢?
简单来说,网页布局的本质就是盒模型摆放的过程。
盒模型的组成
所谓盒模型就是把 HTML 页面中的元素看作是一个矩形的盒子,也就是一个盛放内容的容器。每个矩形都是由元素的内容、内边距(padding)、边框(border)和外边距(margin)组成。
[ 盒子的计算尺寸 ]
大多数浏览器,如 Firefox、IE6+ 都采用了 W3C 规范,符合 CSS 规范的盒模型的总宽度和总高度的计算规则为:
1234567891011121314151617181920 // 外盒尺寸计算(元素空间尺寸)Element空间高度 = content height + padding + border + marginElement空间宽度 = content width + padding + border + margin// 内盒尺寸计算(元素大小)Element Height = content height + padding + border // Height为内容高度Element Width = content width + padding + border // Width为内容高度// 注意:width属性和height属性仅适用于块级元素,对行级元素无效(img和input除外);// 计算盒模型的总高度时,还应考虑上下两个盒子垂直外边距合并的情况。// 如果一个盒子[ 没有给定宽度/高度或继承父元素的宽度/高度(本质上也没有给定宽度或高度) ],则padding不会影响盒子的大小。例:<div>Hello World!</div> // 默认宽度为100%,padding左右后仍然为100%;<style>height:30px;border:1px solid red;padding-left:30px;/*width:100%;*/ // 如果加上了width:100%,padding左右后,宽度为100%+30px,产生了影响。</style>[ 盒模型布局的稳定性 ] 刚接触盒模型时,可能最大的困惑是:分不清内外边距的使用。即,什么情况下使用内边距,什么情况下使用外边距?— 其实,它们在大部分情况下是可以混用的,也就是说觉得哪个方便用哪个。
当然,从稳定性的角度考虑,建议:优先使用 width(宽度)> padding(内边距)> margin(外边距)。因为:
- margin 可能发生外边距合并的现象,且在 IE6 下存在 margin 加倍的 bug(讨厌),所以,最后使用;
- padding 会影响盒子大小,需要进行加减运算(麻烦),所以,其次使用;
- width 没有问题,可以使用宽度剩余法或高度剩余法来实现布局,所以,优先推荐使用。
[1] content(内容区) // { CSS3自适应宽高?↓}
[ 宽高 ]内容区由width(宽度)、height(高度)两个属性设置,content = width * height 。
width被定义为从左内边界到右内边界的距离,height被定义为从上内边界到下内边界的距离。
[ 怪异盒模型 ] IE6-浏览器的宽高定义的是可见元素框的尺寸,而不是元素框的内容区尺寸。
1 2 3 4 5 6 |
width:<length> | <percentage> | auto | inherit 默认值为auto,浏览器根据不同的情况设定 引申:max-width、min-width height:<length> | <percentage> | auto | inherit 默认值为auto,内容高度 // 宽高和margin可以设置auto。 // 对于块级元素来说,宽度设置为auto,则会尽可能的宽;如果没有显式声明包含块的height,则元素的百分数高度会重置为auto。 |
[ 最大最小宽高 ]
设置最大最小宽高的好处是可相对安全地混合使用不同的单位;使用百分数的同时,也可设置基于长度的限制。
12345678 min-width | min-height // 初始值: 0值: <length> | <percentage> | inheritmax-width | max-height // 初始值: none值: <length> | <percentage> | inherit[注意] IE6-浏览器不支持min-width | min-height | max-width | max-height[注意] 当最小宽度(高度)大于最大宽度(高度)时,以最小宽高的值为准。
[2] 内边距 padding // 兼容性问题?!
padding属性用于设置内边距,即设置边框与内容之间的距离。对于行内元素,左内边距应用到元素的开始处,右内边距应用到元素的结尾处,垂直内边距不影响行高,但会影响自身尺寸,加背景颜色可以看出。
1 2 3 4 5 6 7 8 |
padding:[<length> | <percentage>]{1,4} | inherit // 百分数,相对于包含块的width 值缩写:TRBL // 对面相等,后者省略;四面相等,只设一个;内边距不能为负值。 如, padding:40px 30px 20px 10px; padding:20px; padding:20px 10px; padding:30px 10px 20px; |
[3] 外边距 margin { margin负值、重叠、auto和无效情形?↓ }
margin 用于设置外边距。设置外边距会在元素之间创建“空白”,这段空白通常不能放置其他内容。
1 2 3 4 5 6 7 |
margin:[<length> | <percentage> | auto]{1,4} | inherit 四值顺序:TRBL 【1个值】margin: top | right | bottom | left; 【2个值】margin: top | bottom left | right; 【3个值】margin: top left | right bottom; 【4个值】margin: top right bottom left; |
[ 妙用 - 水平居中 ] margin:0 auto;
123456 外边距可以让一个盒子实现水平居中,需要满足以下两个条件:1. 必须是块级元素;2. 盒子必须指定了宽度(width);然后,给左右外边距都设置auto,就可以实现块级元素的水平居中。例:.demo{ width:1200px;margin:0 auto; }[ CSSRset - 清除元素的默认边距 ] 为了更方便的控制网页中的元素,制作网页时,须清除元素默认的内外边距:
1234 * { padding:0;margin:0; }// 另,外边距可以应用到行内元素,但行内元素是只有左右内外边距的,没有上下内外边距,// 也就是说,上下外边距对行高没有任何影响。[ 现象 - margin合并 ] 使用 margin 定义块级元素的垂直外边距时,可能会出现外边距的合并。
- 相邻块元素垂直外边距的合并 — 毗邻元素垂直重叠会取最大值 // 解决方案:避免就好了
当上下相邻的两个块元素相遇时,如果上面的元素有下边距margin-bottom,下面的元素有上外边距margin-top,则它们之间的垂直间距不是margin-bottom与margin-top之和,而是两者中的较大值,这种现象被称为相邻块元素垂直外边距的合并(也称为外边距塌陷)。
- 嵌套块元素垂直外边距的合并 — 父元素与第一个 / 最后 一个子元素会合并
对于两个嵌套关系的块元素,如果父元素没有上内边距及边框,则父元素的上外边距会与子元素的上外边距发生合并;合并后的外边距为两者中的较大者,即是父元素的上外边距为0,也会发生合并。
解决方案:可以为父元素定义 1px 的上边框或上内边距 或 可以为父元素添加 overflow:hidden 。
[4] 边框 border { 深入了解border?↓ }
元素外边距内就是元素的边框 border,元素的边框是围绕元素内容的内边距的一条或多条线。
1 2 3 4 5 6 7 8 9 10 |
border: [ <border-width> || <border-style> || <border-color> ] | inherit // 边框由粗细、样式和颜色三部分组成 border-width:[<length> | thin | medium | thick]{1,4} | inherit border-style:[solid | dashed | dotted | …]{1,4} | inherit // 默认没有边框 border-color:[color | transparent]{1,4} | inherit // 默认为字体颜色 例,border:1px solid blue; border-width:0 1px 2px 3px; border-style:solid; border-color:#ff0000; |
[ 行内元素 ] 对于行内元素,边框实际上画在各行之外的下一个像素上,由于各行紧挨着,所以其边框会重叠。无论为行内元素的边框设置怎样的宽度,不会对行高有任何影响;但左右边框会分别显示在元素的开始处和结尾处。
[ 表格的细线边框 ] // border-collapse:collapse; 表示边框合在一起。
12 table { border-collapse: collapse; }td { border: 1px solid blue; }
[ 圆角边框 ] border-radius 可以为边框设置圆角(IE8-不支持),四值顺序是:左上、右上、右下、左下。
123 border-radius: none(默认)border-radius: <length>{1,4}[/<length>{1,4}]?如果反斜杠存在,前面的值是水平方向的半径,后面的值是垂直方向的半径;如果没有则水平和垂直方向相等。
溢出及相关
[1] overflow(溢出) { 引申:overflow-x | overflow-y?↓ }
设置盒子里的内容超出时如何设置。当一个元素固定为某个特定大小,但内容在元素中放不下,此时就可以利用overflow属性来控制这种情况。
1 2 3 |
overflow:visible | hidden | scroll | auto // visible 可视; hidden 隐藏;scroll 一直显示滚动条;auto 内容少时无,超出时显示滚动条; |
[2] 裁剪 clip
CSS裁剪clip这个属性平时用的不多,但其实它并不是CSS3的新属性,很早就开始出现了。
一个绝对定位或固定定位元素通过使用属性clip可以改变剪裁区域的形状,但并不改变元素本身的宽高属性。
1 2 3 4 5 6 |
值: rect(top,right,bottom,left) | auto | inherit 初始值: auto 应用于: 绝对定位或固定定位元素 [注意] 默认值auto表示元素的内容不应剪裁 // IE7-浏览器不支持rect(top,right,bottom,left),支持的写法是rect(top right bottom left);而其他浏览器两种写法都支持 |
clip:rect(top,right,bottom,left)中的值不是边偏移,而是距元素左上角的距离。
具体来说,就是top和bottom是表示距离元素上边界的距离;left和right是距离元素元素左边界的距离。这里元素的边界指元素边框外侧。
rect(...)的语法与CSS的其他语法相比不太一样。原因是它基于早期的定位草案,而该草案使用了左上偏移机制。
在CSS2之前,实现这个语法的IE已经成为完备推荐,于是标准从边偏移修改成适用这个实现。
但是,这意味着如果高度和宽度没有明确定义,将无法设置一致的剪裁区域。
clip:rect(...)只允许长度值和auto,不允许有百分数。
如果设置为auto,则相当于将剪裁边界设置为适当的内容边界。
对于top或left设置auto,相当于值为0;对于right或bottom设置auto,相当于值为水平方向的宽度和或垂直方向的高度和
[注意] 该元素水平方向或垂直方向的clip区域的边界是外框外侧,不包括outline
[ clip的应用 ]
1. 隐藏效果
当clip:rect(top,right,bottom,left)中的top>=bottom,或者left>=right时,可实现元素的隐藏效果,效果类似于visibility:hidden;
2. 雪碧图定位
css sprite是一种网页图片应用处理方式,它允许将一个页面涉及到的所有零星图片都包含到一张大图中,然后利用background-position来显示应该显示的区域。而如果使用clip也可以实现同样的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
div{ height:128px; overflow: hidden; } img{ position:absolute; background-color: rgba(0,255,0,0.5); clip:rect(0,auto,128px,0); } img:hover{ margin-top: -128px; clip:rect(128px,auto,auto,0); } |
1 2 3 |
<div> <img src="http://7xpdkf.com1.z0.glb.clouddn.com/sofa_sprite.png" alt="测试图片"> </div> |
3. 歌词演示效果
利用clip和background-clip实现歌词演示效果,实际上通过改变宽度也可以实现,主要用于拓展思路。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@keyframes loop{ 0%{ clip:rect(0,0px,100px,0); } 100%{ clip:rect(0,520px,100px,0); } } .show,.con{ width: 520px; height: 100px; line-height: 100px; font-size: 30px; position:absolute; background-color: lightgreen; } .con{ animation: loop 6s linear infinite; -webkit-background-clip: text; color: red; } |
1 2 |
<div class="show">我曾经跨过山和大海,也穿过人山人海</div> <div class="con">我曾经跨过山和大海,也穿过人山人海</div> |
[3] 拉伸 resize
CSS3新增了resize属性,该属性允许用户通过拖动的方式来修改元素的尺寸。本来resize应该翻译为缩放,但在实际测试中通过resize属性只可以在宽高基础上实现拉伸效果,而无法实现缩放到小于宽高的效果。
1 2 3 4 5 6 7 8 9 10 |
值: none | both | horizontal | vertical none: 用户无法调整元素尺寸 both: 用户可调整元素的宽度和高度 horizontal: 用户只可调整元素的宽度 vertical: 用户只可调整元素的高度 // IE浏览器不支持resize属性。 resize与overflow关系紧密,只有当元素的overflow属性值不是visible时,resize才会起作用 因为文本框本身就具有overflow:auto的属性,所以自带resize属性 |
[注意] 在win7下resize拖拽区域的大小是17px*17px,实际上它就是滚动条尺寸。
[4] 滚动条
滚动条在网页中经常见到,却并没有受到足够的重视;只有当因为滚动条的问题需要处理兼容性时,才进行调试操作。
[5] 可见性 visibility { visibility:hidden & display:none?↓ }
visibility属性常见于与display属性的比较中。但实际上,该属性有自己的一些有趣的用途。
1 2 3 4 5 6 |
值: visible | hidden | collapse | inherit visible:元素可见 hidden:元素不可见,但元素还是会影响文档的布局 // 可以将一个hidden元素的后代元素置为visible,这会使该后代元素正常出现 collapse:在表格中<col>或<colgroup>中使用,表示该列或列组的所有单元格不显示。如果用于非表格元素,collapse与hidden含义相同。 // webkit内核浏览器不支持给<col>或<colgroup>元素使用collapse属性。 |
高级特性
[1] box-sizing:设置width、height的指定区域
CSS3可通过box-sizing指定盒模型,即指定 content-box / border-box,这样计算盒子大小的方式也就发生了变化。
- box-sizing:content-box; 盒子大小为width + padding + border,默认值,符合W3C的标准盒模型;
- box-sizing:border-borx; 盒子大小为width,也就是说,padding和border是包含在width里面的。
1 2 3 4 5 6 7 |
box-sizing:content-box(默认) | border-box | inherit // IE7-浏览器不支持。 // IE浏览器在getComputedStyle得到width/height是按照标准模式计算的,而不论box-sizing的取值 例, width:150px;height:150px;padding:50px;border:5px solid blue; box-sizing:border-box; |
[ CSS盒模型 ]在CSS中,盒模型被分为两种,一种是W3C的标准模型,第二种是IE怪异盒模型。不同之处在于后者的宽高定义的是可见元素框的尺寸,而不是元素框的内容区尺寸。
目前对于浏览器大多数元素都是基于W3C标准的盒模型,但对于表单form中的部分元素还是基于IE的怪异盒模型,如input里的radio、checkbox、button等元素,如果给其设置border和padding它们也只会往元素盒内延伸。
W3C的标准模型下,宽度和高度仅仅包含了内容宽度,除去了边框和内边距两个区域,这样为web设计师处理效果带来了不少麻烦。为解决这个问题,CSS3新增了一个盒模型属性box-sizing,能够事先定义盒模型的尺寸解析方式。
[2] box-shadow 盒阴影 // IE8-不支持
box-shadow 可以为元素设置阴影,但需要注意的是:
- 可以使用多重阴影,但使用过多会造成性能差。
- 边框在内阴影之上,内阴影在背景图片之上,背景图片在背景色之上,背景色在外阴影之上。
- 内阴影对 img 元素没有任何效果。
- 最先写的阴影在最顶层。
- 该属性与border-radius一脉相承,若通过border-radius设置为圆角,则box-shadow的最终呈现也将是圆角。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
box-shadow:none | <shadow> [,<shadow>]* <shadow>:insert? <length>{2,4} <color>? 例,box-shadow:4px 6px 3px 5px red; 可以简单理解为 box-shadow:inset h-shadow v-shadow blur spread color // 水平偏移 垂直偏移 模糊半径(之前内外半径个1.5px模糊) 阴影大小 颜色 h-shadow:必需。水平阴影的位置。允许为负值。 v-shadow:必需。垂直阴影的位置。允许为负值。 blur:可选。模糊半径。 spread:可选。阴影的尺寸。 color:可选。阴影的颜色,默认和文本颜色一致。 inset:可选。将外部阴影(outset)改为内部阴影。 多阴影(内外叠加) 1.外阴影 border-shadow:3px 3px 5px 2px; 2.内阴影 border-shadow:inset 0px 0px 5px red; |
- 模拟边框
1 box-shadow: 0 0 0 10px blue;
- 单侧投影
1 box-shadow: 0 5px 4px -4px black;
- 邻边投影
1 box-shadow: 3px 3px 6px -3px black;
- 双侧投影
1 box-shadow: 5px 0 5px -5px black,-5px 0 5px -5px black;
[3] outline 轮廓 { 深入了解outline?↓ }
轮廓是绘制于元素周围的一条线,位于边框边缘的外围,可起到突出元素的作用。
1 2 3 4 5 6 7 |
outline:[<outline-width> || <outline-style> || <outline-color>] | inherit 描述边框:不占空间,border外;描边,与周围环境进行区分。 // IE7-浏览器不支持 outline-width:<length> | thin | medium | thick | inherit outline-style:solid | dashed | dotted | … | inherit outline-color:<color> | invert | inherit // invert,执行颜色反转(逆向的颜色) |
轮廓outline处在边框边界的外面,它不像边框那样参与到文档流中,因此轮廓出现或消失时不会影响文档流。
即,不会导致文档的重新显示。利用轮廓,浏览器可以合并部分轮廓,创建一个连续但非矩形的形状。
[ 取消轮廓 ] 默认地,轮廓是一个动态样式,只有元素获取到焦点或被激活时呈现。
1 2 3 |
如上图所示,当input元素获得焦点的时候,会显示出一条轮廓线... // 此处关心的不是如何设置边框,而是如何取消边框(取消默认样式),语法为:outline:0; |