在使用CSS进行网页布局时,我们一定离不开的一个东西————盒子模型。盒子模型,顾名思义,盒子就是用来装东西的,它装的东西就是HTML元素的内容。或者说,每一个可见的 HTML 元素都是一个盒子,下面所说的盒子都等同于 HTML 元素。这里盒子与现实中的盒子又有点不同,这里的盒子是二维的。

在这里插入图片描述

盒子的组成


一个盒子由外到内可以分成四个部分:margin(外边距)、border(边框)、padding(内边距)、content(内容)。会发现margin、border、padding是CSS属性,因此可以通过这三个属性来控制盒子的这三个部分。而content则是HTML元素的内容。

盒子的大小


盒子的大小指的是盒子的宽度和高度。大多数初学者容易将宽度和高度误解为width和height属性,然而默认情况下widthheight属性只是设置content(内容)部分的宽和高。盒子真正的宽和高按下面公式计算

盒子的宽度 = 内容宽度 + 左填充 + 右填充 + 左边框 + 右边框 + 左边距 + 右边距

盒子的高度 = 内容高度 + 上填充 + 下填充 + 上边框 + 下边框 + 上边距 + 下边距

为了显得专业一点,我们还可以用带属性的公式表示:

盒子的宽度 = width + padding-left + padding-right + border-left + border-right + margin-left + margin-right

盒子的高度 = height + padding-top + padding-bottom + border-top + border-bottom + margin-top + margin-bottom

上面说到的是 默认 情况下的计算方法,另外一种情况下,widthheight属性设置的就是盒子的宽度和高度。盒子的宽度和高度的计算方式由box-sizing属性控制。

box-sizing属性值

content-box:默认值,width和height属性分别应用到元素的内容框。在宽度和高度之外绘制元素的内边距、边框、外边距。

border-box:为元素设定的width和height属性决定了元素的边框盒。就是说,为元素指定的任何内边距和边框都将在已设定的宽度和高度内进行绘制。通过从已设定的宽度和高度分别减去 边框内边距 才能得到内容的宽度和高度。

inherit:规定应从父元素继承box-sizing属性的值。

box-sizing:content-box时,这种盒子模型成为标准盒子模型,当box-sizing: border-box时,这种盒子模型称为IE盒子模型

盒子成分分析


margin

margin,盒子的外边框,他是完全透明的,开发者只可以设置它的边距。

margin包含了上下左右四条边,开发者可以单独设置每一条边的边距。

  • margin-top:上边距
  • margin-buttom:下边距
  • margin-left:左边距
  • margin-right:右边距

开发者也可以直接使用简写属性margin同时设置四条边的宽度。

margin示例1

/*margin属性后只跟一个值,同时设置四条边的边距相等*/
margin: 10px;
/*下面样式与上面的样式等价*/
margin-top: 10px;
margin-right: 10px;
margin-bottom: 10px;
margin-left: 10px;

margin示例2

/*margin属性后跟两个值,第一个值设置上下边距,第二个是设置左右边距*/
margin: 10px 20px;
/*下面样式与上面的样式等价*/
margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
margin-left: 20px;

margin示例3

/*margin属性后跟三个值,第一个值设置上边距,第二个是设置左右边距,第三个值设置下边距*/
margin: 10px 20px 30px;
/*下面样式与上面的样式等价*/
margin-top: 10px;
margin-right: 20px;
margin-bottom: 30px;
margin-left: 20px;

margin示例4

/*margin属性后跟四个值,第一个值设置上边距,第二个是设置右边距,第三个值设置下边距,第四个值设置左边距*/
margin: 10px 20px 30px 40px;
/*下面样式与上面的样式等价*/
margin-top: 10px;
margin-right: 20px;
margin-bottom: 30px;
margin-left: 20px;

padding

padding表示盒子的内边距(填充)。与外边距不同,padding不是只能完全透明的,可以设置背景颜色和图片。

与margin类似,padding包含了上下左右四条边,开发者可以单独设置每一条边的边距。

  • padding-top:上部填充
  • padding-bottom:下部填充
  • padding-left:左部填充
  • padding-right:右部填充

开发者也可以直接使用简写属性padding同时设置四条边的宽度。这一部分的用法与上面的margin类似,可以参考margin的四个实例。

border

border表示盒子的边界,它可以设置成可见的,样式多样的。

最基本的,border像margin和padding一样可以分别对每一条边进行设置,也可以使用简写属性border进行设置。

  • border-top:上边界
  • border-bottom:下边界
  • border-left:左边界
  • border-right:右边界

当border属性的色值不明确指定时,如border: 1px solid,边框颜色与当前元素的字体颜色color相同。

border实例1

/*使用简写属性,同时设置四条边界,四条边界的宽度、样式和颜色都是一样的*/
border: 2px solid green;
/*下面的样式与上面的样式等价*/
border-top: 2px solid green;
border-bottom: 2px solid green;
border-left: 2px solid green;
border-right: 2px solid green;

除了可以单独对每一条边进行样式设置之外,还可以分别对边界的宽度、样式和颜色进行设置(下面的属性会对四条边进行设置),同样可以使用简写属性border进行设置。

  • border-width:边界宽度
  • border-style:边界样式
  • border-color:边界颜色

border-sytle属性可取值:

  • none:定义无边框。
  • hidden:与 “none” 相同。不过应用于表时除外,对于表,hidden 用于解决边框冲突。
  • dotted:定义点状边框。在大多数浏览器中呈现为实线。
  • dashed:定义虚线。在大多数浏览器中呈现为实线。
  • solid:定义实线。
  • double:定义双线。双线的宽度等于 border-width 的值。
  • groove:定义 3D 凹槽边框。其效果取决于 border-color 的值。
  • ridge:定义 3D 垄状边框。其效果取决于 border-color 的值。
  • inset:定义 3D inset 边框。其效果取决于 border-color 的值。
  • outset:定义 3D outset 边框。其效果取决于 border-color 的值。
  • inherit:规定应该从父元素继承边框样式。

border实例2

/*使用简写属性设置宽度、样式和颜色,同时作用于四条边*/
border: 2px dotted green;
/*下面的样式与上面的样式等价*/
border-width: 2px;
border-style: dotted;
border-color: green;

这还不算完,开发者还可以对单独一条边界单独设置宽度、样式或颜色。以上两组属性都可以作为下面属性的简写属性。

  • border-top-width:上边界宽度
  • border-top-style:上边界样式
  • border-top-color:上边界颜色
  • border-bottom-width:下边界宽度
  • border-bottom-style:下边界样式
  • border-bottom-color:下边界颜色
  • border-left-width:左边界宽度
  • border-left-style:左边界样式
  • border-left-color:左边界颜色
  • border-right-width:右边界宽度
  • border-right-style:右边界样式
  • border-right-color:右边界颜色

border实例3

/*使用简写属性设置宽度、样式和颜色,同时作用于四条边*/
border: 2px dotted green;
/*下面的样式与上面简写样式等价*/
border-width: 2px;
border-style: dotted;
border-color: green;
/*下面的样式与上面简写样式等价*/
border-top: 2px solid green;
border-bottom: 2px solid green;
border-left: 2px solid green;
border-right: 2px solid green;
/*下面样式又与上面三个样式的任意一个样式等价*/
border-top-width: 2px;
border-top-style: dotted;
border-top-color: green;
border-bottom-width: 2px;
border-bottom-style: dotted;
border-bottom-color: green;
border-left-width: 2px;
border-left-style: dotted;
border-left-color: green;
border-right-width: 2px;
border-right-style: dotted;
border-right-color: green;

上面的属性是对各边的宽度、样式和颜色进行设置,下面一些有趣的属性可以让盒子变得更加地有创意、更加好看。

首先,了解一下 边界半径 ,也就是圆角。边界半径由属性border-radius进行控制,这是一个简写属性,像上面提到过的marginpadding等一样,可以有一个、两个、三个或四个值进行设置。同样也可以对盒子的每一个角的半径进行单独设置。

  • border-top-left-radius:左上角
  • border-top-right-radius:右上角
  • border-bottom-left-radius:左下角
  • border-bottom-left-radius:右下角

边界半径可以使用 px、em 等长度单位,也可以使用百分数。

border-radius值的个数以及每个值对应控制的位置:

  • 一个值:设置四个角有相同的边界半径;
  • 两个值:第一个值设置左上角和右下角,第二个值设置右上角和左下角;
  • 三个值:第一个值设置左上角,第二个值设置右上角和左下角,第三个值设置右下角;
  • 四个值:第一个值设置左上角,第二个值设置右上角,第三个值设置右下角,第四个之设置左下角。

border实例4

/*以简写属性的三个值为例*/
border-radius: 10px 20px 30px;
/*下面样式与上面简写属性样式等价*/
border-top-left-radius: 10px;
border-top-right-radius: 20px;
border-bottom-right-radius: 30px;
border-bottom-left-radius: 20px;

开发者还可以设置x半径和y半径的不同,创建椭圆形角。x半径表示水平半径,y半径表示垂直半径。在border-radius属性中,x半径和y半径用“/”分隔,在border-top-left等四个属性中,传入两个值,第一个值表示x半径,第二个值表示y半径。

border实例5

/*简写属性的x半径设置两个值,y半径设置三个值*/
border-radius: 30px 20px / 20px 10px 30px;
/*在简写属性中设置角度时,值与盒子角的映射是x和y分开的,按照上面提到的规则进行映射*/
/*x半径两个值,第一个值控制左上角和右下角,第二个值控制右上角和左下角*/
/*y半径三个值,第一个值控制左上角,第二个值控制右上角和左下角,第三个值控制右下角*/
border-top-left-radius: 30px 20px;
border-top-right-radius: 20px 10px;
border-bottom-right-radius: 30px 30px;
border-bottom-left-radius: 20px 10px;

图形边界

图形边界是用图形来作为盒子的边界border。我将这一部分单独作为一个小节的原因是,图形边界border-image是CSS3新增的内容,实现起来比较复杂,而且只有一些版本比较新的主流浏览器支持。

在这只图形边界之前,需要先设置一个边界,让图形有显示的空间,同时也可以让不支持图形边界的浏览器显示这个预先设定好的非图形边界。然后,还需要将背景颜色和背景图片限制在填充和内容之内(默认情况下,背景颜色和背景图片作用在border,padding和content,边界的样式浮在背景之上),这需要用到background-clip属性。

background-clip属性的值:

  • border-box:背景延伸到边框外沿(但是在边框之下)。
  • padding-box:边框下面没有背景,即背景延伸到内边距外沿。
  • content-box:背景裁剪到内容区 (content) 外沿。
  • text:背景被裁剪为文字的前景色(只有chrome支持)。

在图形边界中用到以下属性:

  • border-image:设置图形边界,简写属性
  • border-image-source:图形的来源(路径),可以接收一个URL函数或一个渐变作为值。
  • border-image-slice:图形的切片大小
  • border-image-width:图形边界的宽度
  • border-image-repeat:定义图片如何填充边框
  • border-image-outset:定义边界内部和内边距之间的额外空间的大小

可能有很多小伙伴看不懂,没关系,下面对以上属性进行详细的解释。

border-image-source

从图形的来源开始说起。图形的来源可以是一个图片或者渐变颜色。设置图片用URL(path)函数,设置渐变颜色用linear-gradient(to top|bottom|left|right, beginColor1, endColor2)函数。还有一个默认值none,当使用默认值的时候,或者如果图像无法显示,则使用边框样式border-style。有了图形还不行,还需要对图形进行切割,才能够应用到边界上。

border-image-slice

该属性将图片切割成9个区域,包括四个角,四条边以及中心区域。四条切片线,从它们各自的侧面设置给定距离,控制区域的大小。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88tKMWop-1575875310422)(https://developer.mozilla.org/files/3814/border-image-slice.png “图片切割方法”)]

上图中,四条切片线将图片切成了9份。其中1、2、3、4为四个角区域,将会对应应用到盒子边界的四个角;5、6、7、8为四个边界区域,将会对应应用到盒子边界的四条边;区域9为中心区域,默认情况下会被丢弃,但如果设置了fill关键字(可以被设置在属性的任何一个位置(前面、后面或者两个值之间)),则会将其作为背景图形。

border-image-slice属性的值可以是数字或百分数,还有关键字fill。值的个数可以是1-4个,其规则与marginpadding等属性一样。

border-image-repeat

该属性设置图片在边框的填充方式。值的个数可以是一个或两个,一个值时设置所有的边框,两个值时分别设置水平与垂直的边框。它具有下面的值:

  • stretch:拉伸图片以填充边框。
  • repeat:平铺图片以填充边框。
  • round:平铺图像。当不能整数次平铺时,根据情况放大或缩小图像。
  • space:平铺图像 。当不能整数次平铺时,会用空白间隙填充在图像周围(不会放大或缩小图像)
  • inherit:继承父级元素的计算值。
border-image-width

设置图形边界的宽度。当border-image-width的值大于border-width时,图形不会向margin方向扩展,而是会向padding和content方向扩展,覆盖。

border-image-width属性的值可以是长度或百分数,以及auto。值的个数为1-4个,其规则与marginpadding等属性的规则一致。

border-image-outset

该属性设置边框图像可超出边框盒的大小。讲的通俗一点,就是在图像和padding之间增加一些填充,将边框图像往外挤。它的值可以是长度或百分数,值的个数为1-4个,其规则与marginpadding等属性的规则一致。

border-image

该属性是一个简写属性,他可以设置上面提到的五个属性,其基本语法如下:

<'border-image-source'> || <'border-image-slice'> [ / <'border-image-width'> | / <'border-image-width'>? / <'border-image-outset'> ]? || <'border-image-repeat'>

关于“||”、“?”等符号的意义可以查看CSS属性值定义语法

border-image实例

background:blue;
background-clip: padding-box;
border: 20px dotted green;
border-image:url(https://mdn.mozillademos.org/files/13060/border-image.png) 40 / 10px / 20px round;
/*其中border-image属性可以用以下一组属性代替*/
border-image-source: url(https://mdn.mozillademos.org/files/13060/border-image.png);
border-image-slice: 40;
border-image-width: 10px;
border-image-outset: 20px;
border-image-repeat: round;

盒子阴影

在盒子的组成成分之外,CSS3给盒子添加了阴影。盒子的阴影由box-shadow属性控制,阴影的轮廓与盒子边界border的轮廓一样。该属性的正规语法如下:

none | [inset? && [ <offset-x> <offset-y> <blur-radius>? <spread-radius>? <color>? ] ]#
  • inset:默认阴影在边框外。使用 inset 后,阴影在边框内(即使是透明边框),背景之上内容之下。
  • offset-x, offset-y:这是头两个长度值,用来设置阴影偏移量,相对于border外边线开始计算offset-x 设置水平偏移量,如果是负值则阴影位于元素左边。offset-y 设置垂直偏移量,如果是负值则阴影位于元素上面。如果两者都是0,那么阴影位于元素后面。这时如果设置了 blur-radiusspread-radius 则有模糊效果。
  • blur-radius:这是第三个长度值。值越大,模糊面积越大,阴影就越大越淡。 不能为负值。默认为0,此时阴影边缘锐利。
  • spread-radius:这是第四个长度值。取正值时,阴影扩大;取负值时,阴影收缩。默认为0,此时阴影与元素同样大。
  • color:如果没有指定,则由浏览器决定——通常是color的值,不过目前Safari取透明。

设置多个阴影时,使用逗号将每个阴影的值隔开。前面的阴影会在后面阴影之上,如果上层有透明度较低的部分,会与下层的颜色重叠,合成新颜色。

border-shadow实例

/* offset-x | offset-y | color */
box-shadow: 60px -16px teal;

/* offset-x | offset-y | blur-radius | color */
box-shadow: 10px 5px 5px black;

/* offset-x | offset-y | blur-radius | spread-radius | color */
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);

/* inset | offset-x | offset-y | color */
box-shadow: inset 5em 1em gold;

/* 多个阴影*/
box-shadow: 3px 3px red, -1em 0 0.4em olive, 5px 10px 5px 5px green;

/*全局关键字*/
box-shadow: inherit;
box-shadow: initial;
box-shadow: unset;

浏览器兼容性


本部分内容引用w3cSchool CSS教程的CSS盒子模型

一旦为页面设置了恰当的 DTD,大多数浏览器都会按照上面的图示来呈现内容。然而 IE 5 和 6 的呈现却是不正确的。根据 W3C 的规范,元素内容占据的空间是由 width 属性设置的,而内容周围的 padding 和 border 值是另外计算的。不幸的是,IE5.X 和 6 在怪异模式中使用自己的非标准模型。这些浏览器的 width 属性不是内容的宽度,而是内容、内边距和边框的宽度的总和。

虽然有方法解决这个问题。但是目前最好的解决方案是回避这个问题。也就是,不要给元素添加具有指定宽度的内边距,而是尝试将内边距或外边距添加到元素的父元素和子元素。

IE8 及更早IE版本不支持 填充的宽度和边框的宽度属性设。

解决IE8及更早版本不兼容问题可以在HTML页面声明 <!DOCTYPE html>即可。

参考

[1] w3cSchool CSS教程

[2] MDN Styling boxes

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐