純 CSS實現根據元素已知的寬度設定高度以及注意事項
一個移動端的小需求,元素的寬度根據螢幕寬度進行獲取,也就是實時獲取,可以當成單位是 百分比%
,要求元素表現為正方形,也就是說高度要等於寬度。
發現這個需求的時候,我第一時間就是想用 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% 0 0;
}
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
等,都是為了能讓元素的高度符合預期而進行的一些聊勝於無的保障措施。
不過在使用這種技巧的時候,有些小問題可能需要稍微注意一下。
將程式碼改一下:
// HTML
<div class="box">
<img src="https://dummyimage.com/400x500/ff3ff3)" alt="">
<span>666</span>
</div>
// CSS
.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;
的上下之和。