一个移动端的小需求,元素的宽度根据屏幕宽度进行获取,也就是实时获取,可以当成单位是 百分比%
,要求元素表现为正方形,也就是说高度要等于宽度。
发现这个需求的时候,我第一时间就是想用 js
来控制,根据屏幕宽度来计算出元素宽度值,并将元素的高度也赋值成这个值,这样一来就实现元素的宽度、高度一致了,没什么难度,几行代码嗖嗖地搞定。
不过这个需求其实只是我正在做的项目的一个小点而已,我当时正在专心致志地写 css
,做过稍大一点项目的人都知道,各种切换代码最烦了,宁愿在浏览器上另开一个窗口看看有没有其他的办法也不想切换项目文件夹来回折腾,所以我就网上搜了一下,确实让我看到了一个方法。
不说废话,先上代码:
// HTML
<div class="box">
<img src="https://dummyimage.com/400x500/ff3ff3)" alt="">
</div>
// CSS
.box {
position:relative;
width:40
height:0;
font-size:0;
line-height:0;
padding:40
}
img {
position: absolute;
width: 100
height: 100
}
看看效果

嗯,确实很棒,.box
的宽度和高度完全一致,内部元素 img
的宽高也都能被完美控制
CSS
代码中,最关键的就是这一句:
padding:40% 0 0;
这里的 40%
就是宽度 width
的值,二者相等,则宽高就相等,那么为什么这样可以呢?
既然是与 padding
有关,那么很自然先去 MDN上看一下关于 padding
的定义:

大概的意思是:
padding
的值可以设置为两种类型。
1. 一种是固定值(例如 px
单位),必须是正值;
2. 第二种则是百分比值(%
),此时 padding
的大小是相对于元素的 宽度的百分比,必须是正值。
看到规范后恍然大悟, padding
用了那么多年,原来这里的百分比是相对于元素宽度的大小,以前一直以为如果是上下 padding
,则是相对于高度,左右padding
就是相对于宽度的,看来想要娴熟地使用一门技术,规范还是要多多看看的。
知道了以上后,我们就很清楚了,这里的 padding:40% 0 0;
同样可以换成 padding:0 0 40%;
,或者 padding-top: 40%;
或者 padding-bottom: 40%;
,至于其他的一些样式,例如 height:0; font-size::0
等,都是为了能让元素的高度符合预期而进行的一些聊胜于无的保障措施。
不过在使用这种技巧的时候,有些小问题可能需要稍微注意一下。
将代码改一下:
<div class="box">
<img src="https://dummyimage.com/400x500/ff3ff3)" alt="">
<span>666</span>
</div>
.box {
position:relative;
width:40%;
height:0;
font-size:0;
line-height:0;
padding:40% 0 0;
}
img {
position: absolute;
width: 100%;
height: 100%;
}
span {
position: absolute;
bottom: 0;
padding: 4px;
font-size: 20px;
background-color: skyblue;
}
增加了一个 span
元素,在我想象中,效果应该是这样的:

然而,实际上它是这样的:

什么情况?
skyblue
的背景明明是应该包裹着文字而且比文字稍大才对,怎么连同文字一起缩下去了?
对着代码看了半天,也没看出来哪里错了,无奈之下只好使用删码
大法(将样式逐行删去查看效果,并与之前的进行对比),在删到 line-height:0;
的时候终于定位了,原来问题出在这里。
虽然使用 padding
元素,将原本 height: 0;
的元素,硬生生给撑开了,但这些撑出来的高度实际上还是被 padding
给占据了,根本没有给子元素留空间,里面的子元素就只能被挤压到父元素外面了
如果你给.box
元素增加一个 overflow:hidden;
的样式,就会发现父元素整个消失了,因为父元素本来就没有高度,所以就把 padding
给硬撑出来的高度给 hidden
掉了,子元素因为是绝对定位,所以既然被挤出了父元素也不会被 hidden
掉。
至于 line-height
,实际上真要说起来其中还是有很多学问的,在本例中,之所以 line-height: 0
能让元素变’扁’了,就是因为其改变了文本撑出来的line
高度,导致padding: 4px;
不是以文本作为参考,而是以高度 0
作为参考,如果审查元素的话,你就会发现那变’扁’了的 skyblue
背景的高度其实是 8px
,正好是 padding: 4px;
的上下之和。