inline-block元素設置margin-bottom為負值後為什麼會下移?
如圖,inline-block元素設置margin-bottom為負值後為什麼會下移?
典型的 IFC 知識點問題
行框 的高度是當前所有 行內框 根據 vertical-align 值進行垂直方向對其後,由當前行所有 行內框 最高的頂邊和最低底邊的實際距決定的。
在這裡 vertical-align 值是默認的 baseline,對應的行內框是 inline-block box,那麼 basline 對其的將是 inline-block 的 margin-bottom 邊界。
nth-child(2) 元素 margin-bottom 為負值,導致 margin-bottom 邊界提升到其 border 底邊界之上 ,兩側 inline-block box 依然用其 margin-bottom 來對其上升的 nth-child(2) 元素底邊界。這樣兩側的元素的 border 底邊界已經顯示在 nth-child(2) 元素的 border 底邊界之上。
但是其 行框高度 實際值推算值是完全沒有變化的(當前行內框的最高頂邊和最低底邊差值不變,-20px 已經被兩側元素對齊時提升的 20px 抵消了)。
行框間又具有不重疊特性,不會侵入其上下相鄰的行框(也不會向上溢出其包含塊),實際上整體行框下移後為其排布位置。
這樣導致看起來是 nth-child(2) 元素是 border 邊界下移的排布結果。
同理,若此時nth-child(2) 元素 的 margin-top 為負值,nth-child(2) 底邊界連同 border 底邊界一起提升,兩側 inline-block box 依然用其 margin-bottom 來對其上升的 nth-child(2) 元素底邊界。提上後所有元素頂邊界又回歸視覺對齊,且實際行框高度並無變化,導致看起來 margin-top 為負值無效。
PS:注意區分 行框 line box 和 行內框 inline box 概念。
具體的原理我也描述不清楚。簡單的回答自己知道的幾點:
在規範中`display`取值為`inline-block`,是這樣描述的:
This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
大致的意思,會讓元素生成一個`linline-level`塊容器,而一個`inline-block`內格式化之後類似於block box,但是元素自身卻被格式化一個原子類linline-level box。
反正這樣的描述蠻蛋疼的。不過這裡說到的inline-block元素,那麼他的對齊方式和vertical-align是非常有關係的,默認情況下:
是以`baseline`為基礎對齊,這個時候就又引出來baseline的概念了。要了解這個概念和line-height之類的又有關係了。把正複雜,蛋疼。咱先不說。繼續說對齊。如果把第二個元素內容去掉:
是不是覺得非常的神奇。回到規範中,CSS2的可視化格式模型文檔中有一么一段話:
The baseline of an 『inline-block』 is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its 『overflow』 property has a computed value other than 『visible』, in which case the baseline is the bottom margin edge.
大至意思:
『inline-block』的基線是正常流中最後一個line box的基線, 除非,這個line box裡面既沒有line boxes或者本身』overflow』屬性的計算值而不是』visible』, 這種情況下基線是margin底邊緣。
通俗的話描述就是:
一個inline-block元素,如果裡面沒有inline內聯元素,或者overflow不是visible,則該元素的基線就是其margin底邊緣,否則,其基線就是元素裡面最後一行內聯元素的基線。
把你的demo稍為修改一下,先把第二個margin-bottom幹掉
繼續變一下,並在第二個中加方字:
這個沒有添加任何margin-bottom,第二個成這樣了。
會發現,明明尺寸、display水平都是一樣的,結果呢,兩個卻不在一個水平線上對齊,為什麼呢?哈哈,上面的規範已經說明了一切。第一個框框裡面沒有內聯元素,因此,基線就是容器的margin下邊緣,也就是下邊框下面的位置;而第二個框框裡面有字元,純正的內聯元素,因此,第二個框框就是這些字元的基線,也就是字母x的下邊緣了。於是,我們就看到了框框1下邊緣和框框2裡面字元x底邊對齊的好戲。
其實看到這裡,你應該知道一些原因了。把div的文字去掉,然後加上margin-bottom。其實也是改變了元素的baseline了(你就當作改變了)。
如果你在div中添加一個vertical-align改變他的對齊方式。就變了:
有關於inline-block元素和vertical-align相關的測試demo,可以看看:https://www.brunildo.org/test/inline-block.html
感覺並沒有解釋清楚,建議查規範吧,因為規範有對這些方面的描述,只是要理解規範中的英文還是蠻蛋疼的。推薦兩篇文章:
CSS深入理解vertical-align和line-height的基友關係 quot; 張鑫旭-鑫空間-鑫生活
深入了解CSS字體度量,行高和vertical-align_CSS, line-height 教程_w3cplus
如何理解CSS的display屬性_CSS 教程_w3cplus
沒有內容的行內塊元素的baseline是以塊的底邊算的,現在你把margin-bottom設置成負的了,相當於底邊向上了,即baseline向上了,而默認的對齊方式是baseline,so~
別的元素一樣會下降啊。。。
這個 問題要解釋清楚,你可能要邀請張鑫旭、大漠等資深重構了。
inline-block並排的時候本身也是IFC模型,涉及到vertical-align之類難以理解的知識,margin上下默認會基於基線來位移,這個表現也比較難以理解。
反正我是答不清楚的了。
瀉藥。
marginbottom這個值確實是很詭異的,通常不會設定負值,如果用負值也不會報錯,但是會把你這個元素外面隱藏的邊框壓縮到0後再反向壓縮,慢慢增大負值 ,框內元素會往上走值到飛出你的視野…
還是建議用dw來編寫css好一些。當margin-bottom為20px的時候,是基於該盒模型底部向上偏移一個20px。如果此時是-20px,那就基於盒模型底部向下偏移20px~
感覺也說不出來為什麼, 行內格式設置margin的效果可能就是參考某一條baseline吧。按理來說margin的參考應該是兄弟節點, 或者是帶邊框的父節點。不過css這個東西深入研究為什麼得看底層的實現了, 如何操作渲染引擎的。一般就按規矩辦事就好了
推薦閱讀:
※工作中常用的HTML+CSS布局有哪些可以總結出的模式?
※CSS 中 a 標籤為什麼不能繼承父類的顏色?
※css偽元素:after和 :before 存在的意義?
※除了聖杯布局和雙飛翼布局還有其他哪些比較有特點的布局方法?
※CSS 屬性 display 取值 box 和 flexbox 以及 flex 有什麼不同,分別表示什麼?