CSS 盒模型


经典图解


如上图所述,每个 HTML 元素,都像一个盒子,而这个盒子,有content(内容),padding(填充缝隙),border(边界/外壳),margin(边缘空白)。

  • content:可以理解为盒子里装的内容物
  • padding:可以理解为盒子的外壳和内容之间的缝隙(或者是填充物),就像快递盒子里面可能会填上那种充气的保护垫
  • border:可以理解为盒子的外壳
  • margin:可以理解为盒子与盒子间的空隙

相关属性

width 元素宽度

width:<length>|<percentage>|auto|inherit</span>

解释:

  • 该属性,很明显,是用来设置元素宽度的,但是具体设置的是content部分的宽度,还是border包含的部分的宽度,要视情况而定,本篇后面会讲
  • 一般对于inline(行级)元素设置宽度是没有意义的,只给inline-blockblock或者其他某些类型的元素设置宽度
  • 默认值是auto,没有继承性,除非设置了inherit
  • 引申出min-widthmax-width属性,是给元素设置最小宽度和最大宽度的

height 元素高度

height:<length>|<percentage>|auto|inherit</span>

解释:

  • width一致

padding 填充宽度

padding:[<length>|<percentage>]{1, 4}|inherit</span>

解释:

  • padding是设置填充宽度的一个属性。可以设置 1 到 4 个值,分别设置上、右、下、左(顺时针)四个填充宽度,如上图。
  • 设置为<percentage>时,百分比数值是相对父元素
  • 也可以分开设置padding:padding-top,padding-right,padding-bottom,padding-left
  • 举例说明:
    • 写一个值的情况:padding:20px;,说明四个方向的padding都是同一个值,也就是 20px
    • 写两个值的情况:padding:20px 10px;,其实等于padding:20px 10px 20px 10px;,也就是说,如果上和下的padding相等,那么只要设置一个就够了,左右也是一样。
    • 写三个值的情况:padding:20px 10px 5px;,其实等于padding:20px 10px 5px 10px,事实上写三个就只指定了上,右和下的宽度,剩余的左宽度应该等于右边的宽度。
  • 总结一下规则:
    • 对面相等,后者省略
    • 四面相等,只写一个
  • 其实类似padding这样,要对四个方向设值的属性,一般都可以像padding的规则进行设置。
  • padding的颜色和content的颜色一致,都是background-color

margin 外边距宽度

margin:[<length>|<percentage>|auto]{1, 4}|inherit</span>

解释:

  • margin的书写方式基本上和padding是一样的,但是还是有一些区别的。
  • margin默认为 0,但是可能浏览器的默认样式表会给某些标签设置初始margin值,比如 IE6、IE7 的 body 标签,默认的样式应该是:display:block;margin:15px 10px;zoom:1;(不是很确定),而没有预设 padding 值,chrome/firefox 也只是设置了margin:8px;没有预设 padding
  • 上下毗邻的两个元素的margin-topmargin-bottom会合并,取两者之间的较大值,看下面这个例子,两个元素间距仅为 30px,而不是 30px+10px:
    1
    2
    <div style="height:30px;width:100px;margin:30px 10px;background-color:lightseagreen;"></div>
    <div style="height:30px;width:100px;margin:10px 10px;background-color:lightseagreen;"></div>
  • 父元素的上下margin分别会和第一个子元素的margin-top以及最后一个子元素的margin-bottom进行合并。
    1
    2
    3
    4
    <div style="width: 100px; margin: 40px auto; background-color: lightblue;">
    <div style="height:30px;width:100px;margin:30px 0;background-color:lightseagreen;"></div>
    <div style="height:30px;width:100px;margin:10px 0;background-color:lightseagreen;"></div>
    </div>

    但值得注意的是,上面这种情况的触发条件是比较苛刻的。只有在父元素没有设置border的时候才会合并。因为子元素的所有内容(包括margin)是要完全包含在父元素的border里面的。假设,我在上面这种情况中,给父元素添加border,就会变成下面这种情况:

border 边框

border:[<border-width>||<border-style>||<border-color>]|inherit</span> > border-width:[<length>|thin|medium|thick]{1,4}|inherit</span> > border-style:[solid|dashed|dotted|…]{1,4}|inherit</span> > border-color:[<color>|transparent]{1,4}|inherit</span> > border-radius:[<length>|<percentage>]{1,4} [/[<length>|<percentage>]{1,4}]

解释:

  • 上面的属性,都可以写成border-direction-xxx的形式,如border-bottom-color
  • border-style最常用的三种就是:solid(实线), dashed(虚线), dotted(点线)
  • 重点讲一下border-radius
    - 事实上,每个角都是一个椭圆,而椭圆都会有两个属性,就是 x 轴长度和 y 轴长度,如图所示。 - 所以设置全部四个角,需要 8 个值来表示,前四个,分别表示 1,2,3,4 个角的 X 轴方向半径,而后四个,则需要在前面加上/以示区别。比如上图中的圆角矩形,可以写成border-radius: 10px 15px 5px 5px /10px 5px 5px 15px。 - border-radius也满足对面相同,后者省略;四面相等,只写一个的规则,也就是,如果 1 号角和 3 号角如果一样,则只要写 1 号角的就行了。 - border-radius还满足x,y 一致,后者省略的规则,也就是说如果 x 方向半径和 y 方向半径一致的话,y 方向就可以不写 - 对border-radius设置百分比的值时,是相对本元素的widthheight而言的。也就是说,如果对一个正方形元素,设置border-radius:50%就可以变成圆形,如下:

outline 轮廓

outline:[<outline-width>||<outline-style>||<outline-color>]|inherit</span>

outline-width:[<length>|thin|medium|thick]|inherit</span> > outline-style:[solid|dashed|dotted|…]|inherit</span> > outline-color:<color>|inherit</span>

解释:

  • outline是在border外面的一圈,不占据空间的轮廓。基本上和border的属性一致。
  • 下面这个例子,你会发现两个div块之间,outline会互相覆盖,这说明outline并不占据空间。
1
2
3
4
5
6
7
8
9
10
11
div {
width: 200px;
height: 50px;
outline: 10px solid rgba(230, 230, 230, 0.5);
}
.left {
background-color: lightseagreen;
}
.right {
background-color: darkorange;
}

overflow 溢出

overflow:visible|hidden|scroll|auto

解释:

  • overflow是用来设置如果子元素超过父元素的溢出规则。
  • visible表示可见;
  • hidden表示隐藏;
  • scroll表示固定显示滚动条;
  • auto表示根据内容多少来选择显示或不显示滚动条;
  • 效果对比:

overflow: visible; overflow: visible; overflow: visible; overflow: visible; overflow: visible; Jackie Anxis

overflow: hidden; overflow: hidden; overflow: hidden; overflow: hidden; overflow: hidden; overflow: hidden; overflow: hidden; overflow: hidden; overflow: hidden; overflow: hidden; Jackie Anxis


overflow: scroll; overflow: scroll; overflow: scroll; overflow: scroll; overflow: scroll; overflow: scroll; overflow: scroll; overflow: scroll; overflow: scroll; overflow: scroll; Jackie Anxis

overflow: auto; overflow: auto; overflow: auto; overflow: auto; overflow: auto; overflow: auto; overflow: auto; overflow: auto; overflow: auto; overflow: auto; Jackie Anxis

  • 也可以利用overflow-xoverflow-y分别设置 X 和 Y 方向的溢出处理

box-sizing 选择宽度设置

box-sizing:content-box|border-box|inherit</span>

解释:

  • box-sizing是用来指定,widthheight指定的究竟是content内容的宽度还是border包含的宽度。
  • 默认是content-box,表示 CSS 样式中,widthheight指定的是content内容的宽度,也就是说,width: 100px;padding:10px;这段代码,实际上border(不包含border)里面的内容应该宽为 120px
  • 设置为border-box,表示 CSS 样式中,widthheight指定的是border(包括border在内)包含内容的宽度。
    -
1
2
3
4
width: 100px;
padding: 10px;
border: 10px;
box-sizing: border-box;

这段代码,实际上,content部分的宽度只有 60px,而要加上paddingborder的宽度才达到 100px。


box-shadow 设置阴影

box-shadow:none|<shadow>[,<shadow>]* > <shadow>:inset?&&<length>{2,4}&&<color>

解释:

  • box-shadow用来设置一个元素的阴影,默认是none,可以是多个值,中间用,隔开,表示多层阴影。
  • inset表示内阴影
  • 对于每一层阴影,length可以有 2-4 个,分别表示水平偏移(正值表示向右)、垂直偏移(正值表示向下),模糊半径,阴影大小;如下图所示的一段 CSS:
1
box-shadow: 10px 10px 5px 20px lightblue;


黑色边框部分,是向下偏移 10px,向右偏移 10px 应该产生的阴影(也就是box-shadow: 10px 10px lightblue;的情况下应该有的大小),而红色边框比黑色边框总共宽 40px(2 个阴影大小的宽度),而 5px 的模糊半径,是包含在 20px 的阴影大小里面的。

关于盒模型中百分比的问题做一个统一说明

width&height

对子元素的widthheight设置百分比值,无论父元素的box-sizing如何,都是相对父元素content部分进行计算的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*left div content-box*/
.parent {
width: 200px;
height: 100px;
padding: 10px;
box-sizing: content-box;
}
.child {
width: 50%;
height: 50%;
}
/*right div border-box*/
.parent {
width: 200px;
height: 100px;
padding: 10px;
box-sizing: border-box;
}
.child {
width: 50%;
height: 50%;
}

100x50
</div>
90x40
</div>

  • 第一个父元素的content-box的宽为200px;所以子元素的width/height应该是基于200px进行计算的。
  • 第二个父元素的content-box的宽为200px-10px*2=180px;所以子元素的width/height应该是基于180px进行计算的。

padding&margin&border

对子元素的paddingmargin设置百分比值,无论父元素的box-sizing如何,都是相对父元素content部分的width进行计算的。
哦,忘了说了。border是不允许设置百分比值的。可怜的border

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*padding-test*/
.parent {
width: 400px;
height: 150px;
padding: 50px;
box-sizing: border-box;
}
.child1 {
width: 200px;
height: 20px;
padding: 5% 16.67%;
}
.child2 {
width: 200px;
height: 20px;
margin: 5% 16.67%;
}

  • 父元素的content-box的宽为400px-50px*2=300px;所以子元素的padding/margin应该是基于300px进行计算的。
  • 注意:无论上下还是左右的padding或者margin,都是相对父元素的width而言的,和height无关。

border-radius

对元素的border-radius设置百分比值,x 轴方向的值是相对于元素border-boxwidth计算的,y 轴方向的值是相对于元素border-boxheight计算的

1
2
3
4
5
6
7
8
9
div {
width: 1000px;
height: 500px;
padding: 200px;
border: 1px dashed gray;
background-clip: content-box;
/*background-clip: border-box;*/
border-radius: 10%;
}

以下是左上角部分截图: