在《HTML5与CSS3基础教程》(第8版)P215有这样一句话:
如果不显式设置宽度和高度,浏览器就会使用auto,对于大多数默认显示为块级元素的元素,width的auto值是由包含块的宽度减去元素的内边距、边框和外边距计算出来的,简单地说,包含块的宽度指的是父元素给元素留出的宽度
熟悉盒模型的话这句话特别容易理解,这里不多说了。
问题1: heigth:auto失效问题
问题描述:
举一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <style> .outer { height: 200px; width: 200px; background-color:pink; text-align: center; vertical-align: center; }
.inner { background-color: blue; width:auto; height: 100; border: 1px solid red; padding: 5px; margin: 10px; } </style> <body> <div class="outer"> <div class="inner"></div> </div> </body>
|
根据上述定义auto的计算方式,不难计算,内部div的width为168px
但是如果我同步将height设置为auto,原本想的是,height可以按照width:auto一样的计算方式得到结果,但是发现,内部div的height为0!
原因解释:
这里需要注意的是:
在块级元素中,width:auto会自适应撑满父元素宽度,这里的撑满是指撑满剩余部分,是需要经过计算的
在内联元素中,width:auto则呈现包裹性,即元素宽度由子元素的宽度决定
而对于height:auto来说,不论是内联元素还是块级元素,height:auto都是呈包裹性的,即元素的高度由子元素高度决定
总结来说,造成上述问题的原因是要理解,height:auto根据块内内容自动调节高度。
问题2:margin:auto垂直方向失效问题
在《HTML5与CSS3基础教程》(第8版)P21继续提到:
如果手动设置width,但将某个外边距设置为auto,那么这个外边距将进行伸缩以弥补不足的部分
如果手动设置width,并将左右边距设为auto,那么两个外边距就会将设为相等的最大值,实现元素居中
问题描述:
看一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <style> .outer { height: 200px; width: 200px; background-color:pink; }
.inner { background-color: blue; width:100px; height: 100px; border: 1px solid red; padding: 5px; margin: auto; } </style> <body> <div class="outer"> <div class="inner">
</div> </div> </body>
|
从图中可以发现,将margin设置为auto后,浏览器自动计算了内部div的margin值以弥补空间
问题是,按照道理来说,margin:auto是将上下左右四个方向都设置为了auto,为什么计算的时候只对左右两个方向有效?上下两个方向无效?
原因解释:
这里我们首先需要理解下面两点:
- 理解auto的概念:auto是自动填充剩余空间的意思
- 理解块级元素的概念:块级元素在默认情况下会占据整行空间,即使元素宽度不是百分之百占据浏览器,浏览器也会给它留出整行的空间
因此,对于内部div来说,如果设置左右外边距为auto的话,计算方式如下:
1
| 外部div的width = 左外边距 + 左边框宽度 + 左内边距 + 内部div的width + 右内边距 + 右边框宽度 + 右外边距
|
但是块级元素的高度是不会自动扩充的,所以它的外部尺寸是不会自动充满父元素的,也没有剩余空间,因此margin上下设置auto不能实现垂直居中
解决办法:通过定位+margin解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <style> .outer { height: 200px; width: 200px; background-color:pink; position: relative; }
.inner { background-color: blue; width:100px; height: 100px; border: 1px solid red; padding: 5px; margin: auto; position:absolute; top: 0; left: 0; right: 0; bottom: 0; } </style> <body> <div class="outer"> <div class="inner"> </div> </div> </body>
|
这里的关键在于:上下左右四个定位全部设置为0,这样就有了多余空间,auto就能平分剩余的空间去实现水平垂直居中
拓展问题:CSS百分比的参照问题
问题描述:
之前在牛客做过这样一道选择题:
当 margin-top、padding-top 的值是百分比时,分别是如何计算的?
A. 相对父级元素的 height,相对自身的 height
B. 相对最近父级块级元素的 height,相对自身的 height
C. 相对父级元素的 width,相对自身的 width
D. 相对最近父级块级元素的 width,相对最近父级块级元素的 width
知识点:
- 参照父元素宽度的元素:padding margin width text-indent
- 参照父元素高度的元素:height
- 参照父元素属性:font-size line-height
- 特殊情况:相对定位的时候,top bottom left right参照的是父元素的内容区的高度与宽度,而绝对定位参照的是最近定位元素包含padding的高度与宽度
实践出真知:margin padding 参照问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <style> .outer { height: 300px; width: 200px; background-color:pink; position: relative; }
.inner { background-color: blue; width:100px; height: 100px; position:absolute; padding-top: 50%; margin-left: 50%; } </style> <body> <div class="outer"> <div class="inner"> </div> </div> </body>
|
原因分析:
假如padding-top是按照height来说,父元素的高度会包含子元素的高度,如果子元素的padding-top继续增加,那么父元素的高度也会增加,因为父元素要包含子元素嘛,这样的话,父元素的高度就成为了一个死循环. 还有一种说法,我们都知道padding-left/right和margin-left/right都是按照宽度来说的,当我们不设置具体的上下左右只设置margin或padding时四个值应该保持为一种类型