CSS-盒子模型

CSS盒子模型概述

所谓“盒子模型”,即是将网页布局中的元素(能设置宽高的元素)进行拟物化的比喻,一个盒子是由“内容--content”(盒子内的物件)、“内间距--padding”(物件和盒壁的距离)、“边框--border”(盒壁)、“外间距--margin”(整个盒子和其它物体的距离)组成,如下示例图:

由于一些“客观”的原因,IE浏览器和支持W3C标准的浏览器(也就是5大主流浏览器)的盒子模型有一定的差异,即IE浏览器的尺寸(“width”和“height”)包含了conent、padding和border宽和高数值之和,它叫做“IE 6盒子模型”(简称“IE盒子模型”);而标准的盒子模型只包含content的宽和高部分的值,它们叫做“W3C标准盒子模型”(简称“标准盒子模型”)。需要注意的是,无论哪种盒子模型的尺寸都不包含“margin”属性的值。

一方面为为了兼容IE浏览器,另一方面是IE的盒子模型在实际的布局中的确更容易控制。所以我们在实际的开发工作中,都是将标准的盒子模型转换为IE的盒子模型。转换方式是将CSS的样式属性“box-sizing”的值设为“border-box”。当然,如果我们要将IE的盒子模型转化为标准的盒子模型也是可行的,即将“box-sizing”的值设置为“content-box”。我们可以动手制作一个简单的页面实例,然后在开发者工具中进行对比查看。

元素宽度“width”

该属性用于设置“非行内元素”(但不包含图像、框架和多媒体等标签)的宽度,但通过该属性设置的宽度有的时候未必就是元素真实的宽度。通过设置“width”的宽度,在“IE盒子模型”中,宽度是由“content+padding+border”组成的,也就是说在“IE盒子模型”中,设置“width”的时候是无需考虑“padding”和“border”值的(这需在这两个属性的值都不大的时候,“padding”和“border”会压缩“content”的可显示空间)。而在“标准盒子模型”中,宽度只包含“content”,元素自带和人为设置的“padding”和“border”值都会增加元素额外的宽度。

在HTML中具有盒子模型属性的显示类型(display)主要有"块元素(block)"、"行内块(inline-block)"和一些特性与它们相近的显示类型,如"表格单元格(table-cell)"、"表格标题(table-caption)"、"列表项(list-item)"等。

“width”属性最常用的两种设置方式为“像素(px)”设置和“百分比(%)”设置。他们的特点如下:

像素设置
优点:该方式去设置宽度更为的稳定,也就是说当一个元素是通过像素去设置元素宽度的时候,该元素的内容,特别是用像素去设置的文本内容也相对稳定,不会因为设备分辨率的不同而在排版显示上有所不同。
缺点:在不同设备上,需要对元素宽度进行修改才能得到最佳的布局效果。如一个在PC端宽度为“960像素”的元素,在手机端就会出现右面大半部分的显示都会被裁切的情况,需要横向滑动才能显示完整内容。
百分比设置
优点:能对不同显示分辨率做出更好的适应。最外层的标签元素(<body>的子节点)若宽度设为“100%”,那无论是在具有“4K”显示分辨率的高清投影大屏幕上,还是在分辨率在几百像素的移动设备上,都能横向占满整个屏幕。现在有人将“百分比布局”称作“流式布局”,是一种应对“移动浪潮”布局的新趋势。
缺点:若采用百分比布局的方式,很多因素难以控制,如采用默认大小的表单元素,HTML5的功能标签,都会给这种布局方式带来麻烦,若是采用多列布局的页面,这种布局方式在移动端上的效果绝对是“灾难性”的。特别是对于缺乏前端开发经验的开发人员而言,这种布局方式经常会出现一些布局效果在意料之外的情况。

百分比设置的布局有一个“相对性”的特点,也就是它的百分比是对于父级元素而言的。百分比布局相对于对于固定像素布局在应对各种设备分辨率来说更有优势,但实际上它们经常一起组合使用,使得布局方式更加的灵活。在布局设计的过程中也应该多思考,多去预测一些可能出现的状况,从而来选择最优的布局组合方式。

元素高度“height”

该属性的作用是用于设置“块级元素”和“行内块元素”的高度,它绝大部分特征、度量单位和盒子模型的计算方式基本上和“width”属性一样。但在CSS的领域里,垂直方向的一些属性总是会出现一些让人“费解”的问题,如垂直居中的属性“vertical-align”,“margin-top和margin-bottom”的重叠,在执行“margin-top”时会让所有父辈元素都被拉到和自己一样的位置(body、div、p元素的顶部对齐了),而我们希望的是p元素顶部距离它父元素div顶部50像素的距离,而div和body仍然保持顶部对齐,等等一系列的小问题。

“width”属性的表现和“height”属性的差异在于,在同样不设置<html>或<body>宽高的条件下,任意“块级元素”和“行内块级元素”使用“widht”属性设置百分比(%)单位都能达到预期的效果,除非对设置了“height”属性的父级元素设置“height”属性,否则无论用多少的百分比去设置元素的高度,该元素的高度都始终为“0”(若标签无内容的情况)。例如,要给一个<body>标签内的一个<article>标签内的<section>标签设置相对于浏览器视窗100%的高度,那得保证从html标签选择器开始,以此往下的body和article对应的选择器都得有一个100%的高度,缺少任何一个,<section>标签的百分比高度属性都不会生效。

外间距“margin”

“margin”我们称他为外间距,是一个具有盒子模型的元素(即通常的“行内块元素”和“块元素”)相对于同级元素父级元素边界的一个距离值,常用单位为像素“px”和百分比“%”。该属性对文本类元素(即“行内元素”)标签在垂直方向上是无效的(水平方向仍然有效),若要对文本类标签元素进行外间距的设置,总是建议将其“display”属性改为“block”、“inline-block”或者一些与这两个值布局表现上相近的值。

“margin”属性有四个分支属性,如下:

  • margin-top
    • 称作“上外间距”,即距离上方同级元素的距离,若上方元素含有“margin-bottom”,则会取它们之间的较大值作为实际间距值。也就是说如果上方元素具有一个“下外间距”的值为50像素,而下方的元素具有一个“上外间距”的值为100像素,那这上下两个元素之间的距离应该为100像素,而不是150像素。而当这些元素含有属性“float”的“left”或者“right”值时它们之间垂直方向上的距离不再是取较大值,而是相加关系,按我们之前所述的那个例子,它们之间的距离就是150像素了。
    • 在使用“margin-top”时需要注意的一个问题是,若该元素为父元素内的首个子元素,则会让父元素与自己的顶部对齐,如果当前元素的父元素是页面内相对于<body>下的首个子元素(相当于“body > main > div”的关系,当前元素是指这个“div”,而它的父元素就是“main”),那<body>也会被拉下来和当前标签的顶部对齐。也就是说当这个子元素具有一个“上外间距”时,<body>的上边界不再和窗口上边缘对齐了。要解决这个问题,常见的解决方案有:
      • 给父元素至少1像素的padding值(也可以是padding-top)
      • 给父元素至少1像素的border,边框颜色可以是透明的
      • 给父元素设置属性“overflow:hidden”(如鼠标悬浮上去才出现的二级导航菜单等情况不建议使用该方案,否则元素会被裁切)
      • 给父元素或者自身一个浮动属性“float”,值为“left”或者“right”均可。该属性会让块级元素的宽度不再是100%,而是由内容决定,表现为一个“行内块元素”的特性
      • 给父元素设置绝对定位属性值“position: absolute”(除非是其它布局需要,否则不推荐该方案)。该属性同样会让块级元素的宽度不再是100%,而是由内容决定,表现同样为一个“行内块元素”的特性
  • margin-bottom
    • 称作“下外间距”,即距离下方同级元素在垂直方向的距离,若下方元素含有“margin-top”,则取较大值作为间距值。若该元素是DOM内最后一个元素,则相当于是给父元素设置了一个下间距(padding-bottom),若父元素已经设置了“padding-bottom”,则与父元素的该值相加取作为与页面底部的间距。该属性不会造成和使用“上外间距”元素一样产生的一些怪异的问题。
  • margin-left
    • 称作“左外间距”,即距离父级元素左边框的距离,若父元素有内间距“padding-left”,则还需要加上该值。也就是,如果一个元素拥有50像素的“左外间距”,而它的父级元素有一个50像素的“左内间距”,则该元素距离父级元素的左边界的距离实际应为100像素(如果父元素带有border属性,则称作是距离它左边框的距离)。
    • 也可以是距离左方同级元素在水平方向的距离,若左方元素含有“margin-right”,则会和该值相加,取两个元素之间间距值的作为间距值。
  • margin-right
    • 称作“右外间距”,即距离父级元素右边框的距离,若父元素有内间距“padding-right”,则还需要加上该值。
    • 也可以是距离右方同级元素在水平方向的距离,若右方元素含有“margin-left”,则会和该值相加,取两个元素之间间距值的作为间距值。无论是“左外间距”还是“右外间距”他们均不会产生任何布局上的怪异问题。

margin”四个方向的值“合四为一”,写法如下:

margin: 10px;
即将“margin”四个方向的值“margin-top”、“margin-right”、“margin-bottom”和“margin-left”都设置为10像素。
margin: 10px 15px;
即将“margin”垂直方向的值“margin-top”和“margin-bottom”设置为10像素,水平方向的值“margin-left”和“margin-right”都设置为15像素。
margin: 10px 15px 20px;
即将“margin”距离上方“margin-top”的值设为10像素,水平方向的值“margin-left”和“margin-right”都设置为15像素,距离下方的“margin-bottom”的值设为20像素
margin: 10px 15px 20px 25px;
即将“margin”分别对应的“margin-top”,“margin-right”,“margin-bottom”,“margin-left”的值设为10像素,15像素,20像素和25像素。

通过对上面“margin”值的设置我们可以发现,在该属性设置三个值的时候是没有同时设置垂直方向,又分别设置左右方向的写法的,这点在以后使用中要注意。

利用“margin”多值设置的方法,我们还产生了一种设计模式,即将“margin”的值设为“0 auto”,可以让一个“块元素”在页面中水平居中。这里也需要注意的是,虽然“margin”四个方向的属性对“行内块元素”是有效的,但这水平居中的设计模式对于它来说是无效的。要让“行内块元素”执行水平居中就要涉及到我们另外一种设计模式了,即“绝对定位+负外边距”的用法,这在我们以后的课程中还会讲到。

另外需要再次指出的是,当元素拥有浮动属性“float”时(值为“left”或者“right”的时候),margin-top和margin-bottom的值不再会重叠,而是相加的关系。但是这样会让块级元素布局设计模式中的一个“居中模式”失效,即“margin: 0 auto”中的“auto”值失效,元素将不再居中,而是由浮动属性“float”的值是“left”还是“right”决定元素是靠左还是靠右布局,但是“margin-left”和“margin-right”为具体的像素或百分比单位时仍然有效。

内间距“padding”

“padding”我们称他为“内间距”(也有称“内边距”、“填充”等),是一个具有宽高样式属性的元素相对于自身元素的内容的一个距离值,常用单位像素“px”。在“标准(W3C)的盒子模型”中,“padding”的值会占据除“width”和“height”所设置值的额外宽高空间,而在“IE盒子模型”中,“padding”所设置的值不会增加元素的宽和高,但会向内占据空间。

“padding”属性的值设置相对于“margin”来说需要考虑的额外因素更少(除了对设置了“background-origin”属性为“conent-box”的元素来说,后面课程会讲到),它的设置的值在垂直方向也不会出现任何“预料外”的情况,它有四种分支属性,如下:

padding-top
设置该元素的边界与自身的内容在上方的间距
padding-right
设置该元素的边界与自身的内容在右方的间距
padding-bottom
设置该元素的边界与自身的内容在下方的间距
padding-left
设置该元素的边界与自身的内容在左方的间距

和“margin”一样“padding”属性的值也有组合起来写的用法,如下:

padding: 10px;
即将元素边界与内容四个方向“padding-top”、“padding-right”、“padding-bottom”和“padding-left”的间距都设置为10像素。
padding: 10px 12px;
即将元素边界与内容上下两个方向“padding-top”、“padding-bottom”的间距都设置为10像素,与内容左右两个方向“padding-left”和“padding-right”的间距都设置为12像素。
padding: 10px 12px 15px;
即将元素边界与内容上方“padding-top”的间距设置为10像素,与内容左右两个方向“padding-left”和“padding-right”的间距都设置为12像素,与内容下方“padding-top”的间距设置为15像素。

与“margin”一样,“padding”属性在设置三个值的时候是没有同时设置垂直方向,又分别设置左右方向的写法的。若要进行这样的设置,请使用四个值的设置方式去进行设置,即将垂直方向(第一个和第三个)的值设为一样,再分别去设置水平方向(第二个和第四个)的值。

在“IE盒子模型”下运用“padding”需要特别注意的是,“padding”的值会占据内容的空间。如在一个高度为“50像素”,“padding-top”和“padding-bottom”均为“10像素”的“行内块”或“块级”元素内,给文本内容设置行高“line-height:50px”并不会达到垂直居中的效果,而要将文本元素的行高设置为“height-(padding-top+padding-bottom)=innerHeight(在JavaScript中“innerHeight”表示内容的高度,“outerHeight”表示元素实际占据的高度)”,即“50-(10+10)=30”才能达到文本在该元素内垂直居中的效果。

元素边框“border”

该属性的作用是为元素添加一个可以指定线宽、线型和颜色的边框。在标准盒子模型中,该属性的分支属性“border-width”所设置的值会增加元素的实际宽度和高度,而在IE盒子模型中“border-width”所设置的值会和“padding”的值共同占据内容的空间。该属性能对任何显示类型的元素设置,包括“行级元素(inline)”。

“border”属性有三个分支属性:

  • border-width
    • 设定边框的宽度。可以为Web技术中常用的度量单位,通常为像素“px”。
  • border-style设置边框的类型,主要有以下可以设定的值:
    • none,无边框
    • solid,实线边框
    • dotted,点线边框
    • dashed,虚线边框
    • double,双线边框
    • groove,3D凹槽边框
    • ridge,3D凸槽边框
    • inset,内浮雕边框
    • outset,外浮雕边框
  • border-color
    • 设置边框的颜色,可以是Web技术中常规的四种颜色值“英文单词”、“HEX”、“RGBa”和“HSLa”。

图片边框“border-image”

该属性并不能作为border的分支属性,而是作为一个独立的属性来使用。它的作用是为边框加入背景图片。一般情况不会使用较复杂的图像作为边框的图片,而是使用一些简单的有规律的九宫格图案,而且最好是宽高等比的。该属性包含以下分支属性:

border-image-source
图片的URL路径,该属性和“background-image”设置背景图片的方式一致
border-image-slice
图片边框的向内偏移量。值为一个纯数字,不能加上单位,否则会导致该属性无效。该属性最多可以有三个值。具体情况如下:
  • 当只有1个值时,表示边框的四个方向边框的向内偏移量
  • 当出现第2个值时,且都为数值时,第一个值表示水平方向边框的向内偏移量,第二个值表示垂直方向边框的向内偏移量;而其中一个值为“fill”时,数值部分仍然表示四个方向边框向内的偏移量,而“fill”表示图片可以替代“background-image”的作用
  • 当出现3个值的时候,第一个值表示水平方向边框的向内偏移量,第二个值表示垂直方向边框的向内偏移量,而“fill”作用同上。“fill”在这个属性中出现的位置没有要求,即可以在前面,也可以在后面,当存在三个值的时候还能在中间(但不推荐放在中间),但是该值只能出现一次
border-image-width
图片边框的相对于等分“九宫格”图像中每一行或列宽度。纯数值或像素值,纯数值表示相对于边框宽度“border-width”的百分比(1表示原图的100%宽高,2表示原图200%宽高,以此类推),而像素值会缩放“九宫格”图像中每一行或列宽度到指定的像素。该属性和“margin”和“padding”以及“border”一样,最多拥有4个值,表示分别对4个方向的图像边框宽度进行设置,其方位顺序也和之前提到的几个属性一样(顺序为:上→右→下→左)。
border-image-outset
边框图像区域超出边框的量。单位为像素。该属性同样可以最多拥有4个值,表示对4个方向的偏移分别进行设置,方位设置顺序和“border-image-width”属性一致。
border-image-repeat
图像边框的排列方式,该属性可以拥有一个或两个值,当拥有两个值时,第一个值表示水平方向边框的排列方式,第二个值表示垂直方向边框的排列方式。该属性主要有4种类型的值:
  • stretch:默认值。表示拉伸图像来填充区域
  • repeat:表示平铺(重复)图像来填充区域
  • round:类似repeat值。如果无法完整平铺所有图像,则对图像进行缩放以适应区域
  • space:类似repeat值。如果无法完整平铺所有图像,扩展空间会分布在图像周围

为了便于理解,接下来我们来做几个固定这些属性的值,只对其中一个属性的值进行改动的示例来进行比较观察。先给上未经尺寸调整的原图,为一张尺寸为“96 × 96”像素的PNG图片(也就是说单个“苹果”的宽高均为32像素)

圆角的盒子“border-radius”

该属性并不能作为border的分支属性,而是作为一个独立的属性来使用。虽然该属性带了一个“border”字样,同样也是用来设置元素的边界,但它和“border”并无太大的关系,它是对元素的“左上”、“右上”、“右下”和“左下”四个角的“圆度”进行设置。该属性能对任何显示类型的元素设置,包括“行级元素(inline)”。

元素的轮廓“outline”

该属性用于设置一个元素的轮廓线,和“border”不一样,“outline”无论在什么“盒子模型”下,都不会占据页面的空间,并且它不能分别去设置各个方向的值,即不能对“top”、“right”、“bottom”和“left”方向的“outline”进行分别设置,只能进行统一设置。在使用“webkit(老版本Chrome浏览器、Safari浏览器以及iOS和Android系统自带浏览器)”内核或“blink(以新版的Chrome浏览器和Opera浏览器为代表)”内核的浏览器中,该属性会在表单元素在获得焦点后自动出现,本意是让用户获得更好的交互体验,但该设定很多时候反而会影响我们对“Web”页面的风格设置,这个时候我们都是将它的值设置为“none”。另外,“outline”属性并不受圆角属性“border-radius”的影响。

和“border”属性大体一致,“outline”有以下分支属性:

outline-width
设置轮廓线的宽度,能为Web技术中常用的度量单位,最常用的为像素“px”。
outline-style
设置轮廓线的样式,和“border-style”一致,这里就不在赘述。
outline-color
设置轮廓线的颜色,和“border-color”一样支持Web的四种“颜色模式”。
outline-offset
设置轮廓线相对元素边界的距离,通常以像素“px”为单位。

可调整元素大小的“resize”

该属性是用于定义“块级元素”的大小是否可以调整、以何种方式(水平方向还是垂直方向)调整,该属性需要配合属性值为“auto”、“hidden ”或“scroll”的“overflow”属性使用,但被调整大小的元素的宽和高不能小于它原始的宽和高。另外,“resize”属性有个特别案例,就是能够对表单元素<textarea>使用,并且无需显示的去设置“overflow”属性。

讲到“resize”这个属性,不得不提到两对属性,即“max-width”和“max-height”,它们分别表示元素允许的“最大宽度”和“最大高度”,与之对应的是“min-width”和“min-height”,它们分别表示元素允许的“最小宽度”和“最小高度”。这四个属性除了在“resize”中运用比较多,在限制<table>单元格的宽高时也非常实用。

元素的阴影“box-shadow”

该属性能够让元素获得一个“阴影”效果,根据颜色的不同,有时候也可以叫做“发光”效果。“box-shadow”属性没有分支属性,它的值是以“组合值”的形式设置的,它最多允许6个值的组合,按值的顺序分别代表:

h-skewing(必要)
阴影在水平方向的偏移,负数是向左偏移,正数是向右偏移,单位为“px”。
v-skewing(必要)
阴影在垂直方向的偏移,负数是向上偏移,正数是向下偏移,单位为“px”。
blur(可选)
阴影的“模糊距离”或“模糊程度”,单位为“px”。
spread(可选)
阴影的扩展范围,若将“blur”设为“0”,该值则相当于一个可以进行位置偏移但不具备“outline-offset”的“outline”,单位为“px”。
color(可选)
阴影的颜色,支持Web技术中的常用颜色模式:“颜色英文单词”、“HEX”、“RGBa”、“HSLa”。
inset(可选)
将默认向外的阴影方向改为向内,也就是“内阴影”。该值可以放在这一串组合值的第一位,也可以放在最后一位。

内容溢出处理属性“overflow”

该属性可以用于HTML和CSS中任何和内容溢出有关的处理,它是一个比较独特的属性,可以用于解决很多麻烦的问题,而且也有自身对内容处理的一些机制。该属性有两个分支属性,即“overflow-x”和“overflow-y”,可以用这两个分支属性单独处理水平方向和垂直方向的内容溢出,而“overflow”是同时处理这两个方向的内容溢出(本课件就是将“内容区域”的“overflow-y”的值设置为“auto”才在这个区域出现垂直滚动条的,而不是整个页面出现垂直滚动条,可以观察一下)。

“overflow”属性和其分支属性可以设置以下值:

visible
默认值。溢出内容不会被处理,溢出内容会超出元素的边界(对于有固定宽或高的元素,或者设置了文本不换行的元素)。
hidden
溢出内容会被隐藏。就和将“text-overflow”属性的值设为“clip”的情况一样,而这个属性通常也需要配合“overflow”的该属性值来一起设置方能达到效果。
scroll
始终滚动条的显示(内容没有溢出时滚动条内没有滑块只有轨道),通过滑动滚动条可以查看溢出元素边界的内容
auto
当内容没有溢出时不会出现滚动条,而内容超出容器边界时才会出现滚动条

移动设备的分辨率

对于移动设备分辨率我们需要具备的一个常识是,手机参数上的分辨率表示屏幕分辨率而非显示分辨率,如“iphone 6/7/8”的浏览器显示分辨率为“375*667”,但它们的屏幕分辨率参数应为“750*1334”,也就是2倍的关系,在更大的屏幕分辨率下比例还会比2倍多一些,甚至3倍的关系,如“iPhone X”的屏幕分辨率为“1125*2436”但实际上它的显示分辨率为“375*812”,也就是3倍的关系了。

阅读剩余
THE END