終于搞懂了 CSS 中的百分比是基于什么工作的了!
大家有沒有對 CSS 中的百分比是如何工作的感興趣?有沒有想過,為什么它有時會亂七八糟,沒啥頭緒?反正我是有,所以今天分享這篇文章,對自己來說是加深理解,同時也希望對大家有所幫助。
什么百分比?
作為百分比,顯然應該有一個目標作為參考源,這個參考一般是父元素。這是正確的,但并不涵蓋所有情況。最正確的答案應該是包含塊(containing block),即包含我們元素的塊且它不必是直接的父元素。
看看下面的例子:
代碼:
- <div class="grandparent">
- <div class="parent">
- <div class="child"></div>
- </div>
- </div>
- .grandparent {
- position: relative;
- width: 200px;
- height: 200px;
- background: #eaeaea;
- }
- .parent {
- width: 100px;
- height: 100px;
- background: #aaa;
- }
- .child {
- position: absolute;
- width: 50%;
- height: 50%;
- top: 25%;
- left: 25%;
- background: red;
- }
在上面的例子中,我創(chuàng)建了 3 個嵌套 div,它們是具有以下特征的3個正方形
- 最外面的組元 div 是一個淺灰色,大小為 4x4
- 父元素 div的顏色為深灰色,大小為 2x2
- 以及分配 50% 大小的紅色子 div
如果百分比單位以父級為來源,則子級的大小應該是它的 1/2,但上面的不是,子級的大小實際上等于父級,也就是祖父級的 1/2。原因是祖父級 div 是子級 div 的真正包含塊,因為子級具有 position: absolute ,對應于在祖父級中設置的 position:relative 。
因此,為了確定哪個是元素的實際包含塊,它完全基于元素本身的 position 屬性。
但是,對于某些屬性,百分比單元的引用源既不是父塊也不是包含塊,而是它本身—— 自身元素。
百分比的屬性
width/height
如上面的例子中看到的,當一個元素為其寬度分配一個百分比值時, width 是基于包含塊的width, height 是基于包含塊的 height。
padding
對于 padding,垂直(padding-top/padding-bottom)或水平(padding-left/padding-right)都是基于包含塊的 height 來計算。
來個例子:
- <div class="parent">
- <div class="child"></div>
- </div>
- .parent {
- background: #eaeaea;
- width: 300px;
- height: 200px;
- }
- .child {
- display: inline-block;
- background: red;
- padding-top: 50%;
- padding-left: 50%;
- }
- .parent {
- position: relative;
- }
線上地址:https://codepen.io/khangnd/pen/powbjEL
在這個例子中:
- 父 div 的大小為 6x4。
- 子 div的大小為 0,但 padding-top 和 padding-left 分別為 50%
最后的結(jié)果是,子元素的大小相當于父級元素 1/2寬度,也就是一個 3x3 的正方形。
margin
與 padding,margin 的百分比(垂直和水平)也是相對于包含塊的寬度來計算。
來個事例:
- <div class="parent">
- <div class="child"></div>
- </div>
- .parent {
- background: #eaeaea;
- width: 300px;
- height: 200px;
- }
- .child {
- display: inline-block;
- background: red;
- width: 50px;
- height: 50px;
- margin-top: 50%;
- margin-left: 50%;
- }
在這個例子中:
- 父級 div 的大小為 6x4。
- margin-top 和 margin-left 分別為 50%
其結(jié)果是,子元素被定位在離父級元素的上邊距和左邊距3個單位的地方(父級寬度的1/2)。
top/bottom/left/right
這4個定位屬性也是基于包含塊的寬度來計算的。
來個例子:
- <div class="parent">
- <div class="child"></div>
- </div>
- .parent {
- position: relative;
- background: #eaeaea;
- width: 300px;
- height: 200px;
- }
- .child {
- position: absolute;
- background: red;
- width: 16.67%;
- height: 25%;
- top: 50%;
- left: 50%;
- }
在這個事例中:
- 父級 div 的大小為 6x4
- 子元素有 position: absolute, top 和 left 分別為 50%
最終結(jié)果,子 div 被定位在離父 div 的頂部邊緣 2個單位的位置(父 div 高度的 1/2),并被定位在離父 div 的左側(cè)邊緣 3 個單位的位置(父 div 寬度的 1/2)。
transform: translate()
一個用于動畫/過渡的不可思議的屬性,它也支持百分比值。然而,這個屬性并不指其包含的塊,而是指其自身。
來個例子:
- <div class="parent">
- <div class="child"></div>
- </div>
- .parent {
- background: #eaeaea;
- width: 300px;
- height: 200px;
- }
- .child {
- background: red;
- width: 100px;
- height: 50px;
- transform: translate(50%, 50%);
- }
在這個事例中:
- 父級 div 的大小為 6x4。
- 子 div 的大小為 2x1,使用 transform: translate(50%, 50%)
最后結(jié)果,子 div 被定位在離父 div 的頂部邊緣 0.5 個單位的位置(自身高度的 1/2),并被定位在離父 div 的左側(cè)邊緣 1 個單位的位置(自身寬度的 1/2)。
background-size
background-size 屬性將百分比單元的復雜性提升到一個新的水平
此屬性的百分比值指的是背景定位區(qū)域,類似于包含塊,但添加了以下 3 個因素:
- 只有內(nèi)容的塊(content-box)
- 帶有內(nèi)容和 padding 的塊 (padding-box)
- 帶有內(nèi)容、padding 和 border 的塊(border-box)
這三個值是由 background-origin 給出,具體看 MDN :https://developer.mozilla.org/zh-CN/docs/Web/CSS/background-origin
來個例子:
- <div class="parent">
- <div class="child"></div>
- </div>
- .parent {
- background: #eaeaea;
- width: 300px;
- height: 200px;
- }
- .child {
- background-image: url(https://d2fltix0v2e0sb.cloudfront.net/dev-rainbow.png);
- background-size: 50% 50%;
- background-repeat: no-repeat;
- background-color: red;
- width: 50%;
- height: 50%;
- }
在這個例子中:
- 父 div 的大小為 6x4
- 子 div 的大小為 3x2,沒有 padding,沒有 border
- 這里使用了一個DEV logo(比例為 1:1 )作為子 div 的背景圖像,背景大小屬性設置為 50% 50%
其結(jié)果是,背景圖像被拉伸為 1.5 x 1 的大小。
background-position與 background-size 類似,background-position 屬性的百分比也依賴于背景定位區(qū)域。
在這個例子中:
- <div class="parent">
- <div class="child"></div>
- </div>
css
- .parent {
- background: #eaeaea;
- width: 300px;
- height: 200px;
- }
- .child {
- background-image: url(https://d2fltix0v2e0sb.cloudfront.net/dev-rainbow.png);
- background-size: 50% 50%;
- background-position: 50% 50%;
- background-repeat: no-repeat;
- background-color: red;
- width: 50%;
- height: 50%;
- }
在本例中,使用了與前面相同的圖像和布局。當我們改變background-position的值時,可以看到一些變化:
- 如果沒有任何值(默認值為0 0),背景圖像將位于左上角。
- 使用 background-position: 0 50%,背景圖片被定位在左邊中間。
- 使用 background-position: 50% 50%,背景圖片被定位在中心。
- 使用 background-position: 100% 100%,背景圖片被定位在右下方。
注意:background-position: 0 50% 是下面的縮寫
- background-position-x: 0
- background-position-y: 50%
顯然,這個屬性的百分比背后有一些計算,而不僅僅是圖像的頂部和左側(cè)邊緣與孩子的距離。通過一些研究和測試,似乎 background-position 屬性在產(chǎn)生一個實際值之前依賴于以下計算。
offset X = (容器的寬度-圖像的寬度) * background-position-x offset Y = (容器的高度-圖像的高度) * background-position-y
在這種情況下:
- 容器作為子 div
- 圖像的寬度/高度是 background-size 的結(jié)果。
font-size
對于 font-size ,百分比值僅指向它的直接父塊。
來個例子:
- <div class="grandparent">
- font-size: 13px
- <div class="parent">
- font-size: 26px
- <div class="child">font-size: 50%
- </div>
- </div>
在這個例子中,我使用與第一個例子相同的布局,字體大小分配如下。
- grandparent 13px
- parent 26px
- child 50%
我們可以清楚地看到,child 的字體大小現(xiàn)在與 grandparent 一樣,是 parent 的1/2。
線上地址:https://codepen.io/khangnd/pen/MWoeXMO
~~ 完,最近一個禮拜都在趕項目,基本都要2點后才能睡,這篇文章是間斷整理好的,現(xiàn)在時間 是 9/20 深夜3點,睡了,感謝大家的觀看。
作者:Khang 譯者:前端小智 來源:dev 原文:https://dev.to/khgnd/understanding-css-percentage-44gd