摘要:給父元素設(shè)置了一個(gè)灰色背景,并且沒有設(shè)置高度,因此高度會(huì)隨著內(nèi)容而擴(kuò)展,設(shè)置為。這個(gè)元素的位置如下圖所示因?yàn)樵厍宄俗蟾?dòng),所以元素下移。由于這條規(guī)則的存在,導(dǎo)致他們折疊后的不能跟的進(jìn)行折疊,因此的高度被撐開。
作者:https://coding.net/u/zhengkenghong
原文:https://blog.coding.net/blog/css-margin
本文著重描述關(guān)于 margin,我們?nèi)粘2惶菀装l(fā)現(xiàn)的“坑”。
盒模型接觸過 CSS 的人應(yīng)該都知道 CSS 的盒模型:
由內(nèi)容邊緣(Content edge)包圍形成的是內(nèi)容盒(Content Box),類推還有內(nèi)邊距盒(Padding Box)、邊框盒(Border Box)、外邊距盒(Margin Box)。
其中內(nèi)容盒、內(nèi)邊距盒、邊框盒的背景由background屬性決定,而外邊距盒的背景是透明的。
關(guān)于 margin 屬性,有幾點(diǎn)可能跟我們的直覺不相符:
如果 margin 的值是百分比,則是相對(duì)于父元素的內(nèi)容盒寬度來計(jì)算的,即使 margin-top 和 margin-bottom 也是如此。因此即使父元素的高寬不相等,子元素的 margin 元素指定了相同的百分比值,則子元素各個(gè)方向的 margin 計(jì)算值都是相等的。
margin-top 和 margin-bottom 值對(duì)行內(nèi)非替換元素(non-replaced inline element)是無效的。因此我們可以指定 img 元素的 margin-top 和 margin-bottom,而非替換行內(nèi)元素(如 i,span 等)設(shè)置 margin-top 和 margin-bottom 卻不會(huì)產(chǎn)生效果。
相鄰的 margin(Adjoining margin)如果兩個(gè)垂直方向上的 margin,它們中間沒有其他垂直 margin,但它們之間不一定相接觸,我們就說這兩個(gè) margin 是垂直毗連(vertical-adjacent)的,包括以下四種情況,滿足其中之一即可:
父元素的 top margin 和第一個(gè)子元素的 top margin
父元素的bottom margin 和最后一個(gè)子元素的 bottom margin
元素的 bottom margin 和與這個(gè)元素相鄰的兄弟元素的 top margin
如果一個(gè)元素,它沒有生成 BFC、沒有包含正常流的子元素、min-height是0、height是0或者 auto,則它的 top margin 和 bottom margin 也是垂直毗連的
如果兩個(gè) margin 滿足以下三個(gè)條件,我們就說這兩個(gè) margin 是相鄰(adjoining)的:
這兩個(gè) margin 是垂直毗連的,即滿足上面四種情況之一
margin 的兩個(gè)元素都是正常流的塊級(jí)元素,并且在同一個(gè) BFC 中
兩個(gè) margin 之間沒有行盒(line box)、清除浮動(dòng)后的空隙(clearance)、padding和 border
margin 折疊(Collapsing margins)margin 折疊,即相鄰的 margin 有可能會(huì)被折疊成一個(gè)。
比如元素 #a 指定了 margin-bottom 為 10px,而它下方的元素 #b 指定了 margin-top 為 20px,如這樣:
元素 #a 的 margin-bottom 和元素 #b 的margin-top 在位置上重疊了,它們之間的距離是 20px,即元素 #b 的 bottom margin 長度,這就是 margin 折疊現(xiàn)象。關(guān)于這個(gè)現(xiàn)象,可以這么理解:
margin 定義的是它與其他盒子之間的最小間距。其中元素 #a 指定了 margin-bottom 為 10px,就表明它下方的元素 #b 與它至少要有 10px 的距離,它指定的是一個(gè)最小值,因此實(shí)際的距離可以比這個(gè)大。
元素 #a 下方的元素 #b 也設(shè)置了 margin-top 為 20px,如果不折疊,則他們之間就有 30px 的距離。如果折疊成了一個(gè) 20px 的距離,則對(duì)元素 #a 來說,它的 margin-bottom 要求至少要有 10px 的距離,是滿足的,而對(duì)于元素 #b 來說,它的 margin-top 要求至少要有 20px 的距離,也是滿足的。
而 margin 折疊的存在,其實(shí)是為了可以在視覺上顯得更美觀,也更貼近設(shè)計(jì)師的預(yù)期。
margin 折疊規(guī)則并不是所有的 margin 都可以折疊,需要滿足以下條件:
垂直相鄰的 margin 才有可能折疊,水平 margin 永遠(yuǎn)不折疊
根元素(即 html 元素)的 margin 永遠(yuǎn)不折疊
如果一個(gè)元素,它的 top margin 和 bottom margin 是相鄰的,并且有清除浮動(dòng)后的空隙(clearance),這個(gè)元素的 margin 可以跟兄弟元素的 margin 折疊,但是折疊后的 margin 不能跟父元素的 bottom margin 折疊。
需要注意的是,margin 并不是只能折疊一次,多個(gè)滿足要求的 margin 都可以進(jìn)行折疊形成一個(gè)折疊后的 margin(collapsed margin)。
并且假如這個(gè)折疊后的 margin 是由 margin A 等折疊而來的,如果有 margin X 跟 margin A 是相鄰的,則我們也認(rèn)為 margin X 跟這個(gè)折疊后的 margin 相鄰。
當(dāng)兩個(gè)或者兩個(gè)以上的 margin 折疊后,margin 的值計(jì)算如下:
如果 margin 都是正數(shù),則取他們當(dāng)中的最大值
如果 margin 中有正有負(fù),則取最大的正數(shù)加上最小的負(fù)數(shù)(如最大的 margin 是 20px,最小的 margin 是 -20px,則他們計(jì)算后的值是 0)
如果 margin 中都是負(fù)數(shù),則取他們當(dāng)中的最小值
幾道思考題浮動(dòng)、定位元素的 margin 不會(huì)和其他任何元素的 margin 發(fā)生重疊,包括它的子元素。
這是因?yàn)楦?dòng)元素脫離了正常流,所以它和其他相鄰元素就不處與同一個(gè)流中,自然不相鄰;又因?yàn)楦?dòng)元素的內(nèi)容盒會(huì)形成一個(gè)新的 BFC,所以浮動(dòng)元素跟子元素不處與同一個(gè) BFC 中,因此它們的 margin 也不能折疊。定位元素同理可得。
inline-block 的元素不會(huì)和其他元素的 margin 發(fā)生折疊,包括它的子元素。
因?yàn)?margin 折疊只會(huì)發(fā)生在塊級(jí)元素上,因此 inline-block 元素的 margin 不會(huì)和兄弟元素折疊,又因?yàn)?inline-block 的內(nèi)容盒會(huì)形成一個(gè)新的 BFC,所以 inline-block 元素本身也不會(huì)和子元素的 margin 發(fā)生折疊
margin 折疊的幾個(gè)栗子 栗子1如果兩個(gè) margin 滿足以下三個(gè)條件,我們就說這兩個(gè) margin 是相鄰(adjoining)的:
兩個(gè) margin 之間沒有行盒(line box)、清除浮動(dòng)后的空隙(clearance)、padding和邊框
針對(duì)這個(gè)條件,我們通過增加 padding 的方式來阻止 margin 的折疊:
如果 #container 沒有下邊框,則 #container 的 bottom margin 和 #inner 的 bottom margin 是相鄰的,因此它們折疊了,并且 #inner 撐開了 #container 元素,所以可以看到 #container 元素的高度變成了 10px,且顯示的是 #inner 的紅色背景
當(dāng)給 #container 添加一個(gè)下邊框,兩個(gè) margin 之間就邊框的阻隔,他們就不相鄰了,因此不能折疊。所以可以看到 #container 被撐開成了 20px,其中 10px 是 #inner 的高度,還有 10px 是 #inner 的 bottom margin,并且由于 margin 是透明的,因此 #container 露出了部分藍(lán)色的背景。
栗子2:如果兩個(gè) margin 滿足以下三個(gè)條件,我們就說這兩個(gè) margin 是相鄰(adjoining)的:
margin 的兩個(gè)元素都是正常流的塊級(jí)元素,并且在同一個(gè) BFC 中
我們通過創(chuàng)建新的 BFC來阻止 margin 的折疊:
如上圖 #container 元素和 #inner 元素同屬于一個(gè) BFC 中,#container 的 top margin 和 #inner 的 top margin 折疊,bottom margin 同理。
但如果讓 #container 跟 #innter 處在不同的 BFC 中,則 top margin 和 bottom margin 都不會(huì)折疊,如:
給 #container 元素增加一個(gè) overflow: hidden 屬性,讓它的內(nèi)容盒生成一個(gè)獨(dú)立的 BFC,而 #inner 處于這個(gè)獨(dú)立的 BFC 中,因此 #container 和 #inner 就處于兩個(gè)不同的 BFC 中了,所以他們的 margin 不能折疊。
栗子3:如果一個(gè)元素,它本身的 top margin 和 bottom margin 是相鄰的,并且有清除浮動(dòng)后的空隙(clearance),這個(gè)元素的 margin 可以跟兄弟元素的 margin 折疊,但是折疊后的 margin 不能跟父元素的 bottom margin 折疊。
給父元素 #container 設(shè)置了一個(gè)灰色背景,并且沒有設(shè)置高度,因此高度會(huì)隨著內(nèi)容而擴(kuò)展,margin 設(shè)置為 50px。
其中有一個(gè)紅色的浮動(dòng)元素 #floated,高寬都設(shè)置為 40px。
給 #cleared 設(shè)置了 15px 的 margin,并且元素的高度、padding、margin 都為0,因此 #cleared 元素的 top margin 和 bottom margin 是相鄰的。這個(gè)元素的位置如下圖所示:
因?yàn)?#cleared 元素清除了左浮動(dòng),所以 #cleared 元素下移。
而 #cleared 元素和 #slibling 元素的 margin 折疊了,因此可以看到他們的位置是重疊的。
由于這條規(guī)則的存在,導(dǎo)致他們折疊后的 margin 不能跟 #container 的 bottom margin 進(jìn)行折疊,因此 #container 的高度被撐開。
如果沒有這條規(guī)則,他們還應(yīng)該跟 #container 的 bottom margin 進(jìn)行折疊,如:
以上這張圖,在去掉了 #cleared 元素的 clear 屬性之后,就不滿足這條規(guī)則了,所以可以看到 #container 的高度就只有 40px,即紅色的浮動(dòng)元素的高度,而 #cleared 元素、#sibling 元素、#container 元素的 margin 都折疊成了一個(gè)。
結(jié)語這篇文章的絕大多數(shù)內(nèi)容都是從官方規(guī)范翻譯而來,同時(shí)也參考也網(wǎng)上一些寫的比較好的文章而寫的一個(gè)介紹性文章,其中有部分內(nèi)容并沒有展開,如 BFC、clearance 等,因?yàn)檫@部分內(nèi)容不是三言兩語就可以解釋清楚,我本人也需要進(jìn)行更深入的學(xué)習(xí)理解,所以請(qǐng)讀者自行查閱相關(guān)文章
參考文獻(xiàn)https://www.w3.org/TR/CSS2/box.html
https://www.w3.org/TR/CSS2/visuren.html
http://www.w3cplus.com/css/understanding-bfc-and-margin-collapse.html
https://segmentfault.com/a/1190000003099116
https://segmentfault.com/a/1190000003096320
http://melonh.com/css/2015/04/28/understand-margin-collapse.html
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/115077.html
摘要:可以試試去掉的會(huì)發(fā)生很奇妙的事呢附加關(guān)于子元素設(shè)置為而引發(fā)的問題。附加關(guān)于開啟硬件加速提升網(wǎng)站動(dòng)畫渲染性能問題。合并后的外邊距的高度等于兩個(gè)發(fā)生合并的外邊距的高度中的較大者。 1. 水平垂直居中問題 這可以說是最經(jīng)典的問題了,水平垂直居中,這個(gè)問題從入門前端一直到面試,甚至到工作之后都會(huì)時(shí)不時(shí)遇到,最近的面試也被問過這之類的問題,這里還是好好總結(jié)一番,以作備忘。公用 HTML 部分: ...
摘要:盒模型要點(diǎn)知識(shí)務(wù)必注意看,這可是前端面試必定會(huì)遇到的問題。盒模型的主要屬性,除繼承外有兩個(gè)值這里不再細(xì)說歷史原因,只說其作用。嚴(yán)格來說與標(biāo)簽大小無關(guān),但是影響視覺上的位置。具象化需調(diào)試指出,如下其中的最外圈的黃色區(qū)域就是了。 盒模型要點(diǎn)知識(shí) 務(wù)必注意看,這可是前端面試 必定會(huì)遇到 的問題。 box-sizing 盒模型的主要CSS屬性,除繼承外有兩個(gè)值: content-box...
摘要:盒模型要點(diǎn)知識(shí)務(wù)必注意看,這可是前端面試必定會(huì)遇到的問題。盒模型的主要屬性,除繼承外有兩個(gè)值這里不再細(xì)說歷史原因,只說其作用。嚴(yán)格來說與標(biāo)簽大小無關(guān),但是影響視覺上的位置。具象化需調(diào)試指出,如下其中的最外圈的黃色區(qū)域就是了。 盒模型要點(diǎn)知識(shí) 務(wù)必注意看,這可是前端面試 必定會(huì)遇到 的問題。 box-sizing 盒模型的主要CSS屬性,除繼承外有兩個(gè)值: content-box...
摘要:與常人的直覺不符的是,實(shí)際上表示視口寬度的,而不是。與類似,表示視口高度的。存在問題它只適用于在視口中居中的場(chǎng)景基于的解決方案伸縮盒是專門針對(duì)這類需求所設(shè)計(jì)的。 相關(guān)基礎(chǔ)知識(shí) 1.內(nèi)部與外部尺寸模型:(w3c草案)親測(cè)google可支持。(http://w3.org/TR/css3-sizing ) 基于原有CSS尺寸特性,可以使CSS更容易描述內(nèi)容自適應(yīng)以及適應(yīng)固定上下文的盒模型: ...
閱讀 2065·2023-04-25 23:30
閱讀 1478·2021-11-24 10:18
閱讀 3119·2021-10-09 09:54
閱讀 2049·2021-10-08 10:05
閱讀 3471·2021-09-23 11:21
閱讀 3189·2019-08-30 15:52
閱讀 1585·2019-08-30 13:05
閱讀 1083·2019-08-30 13:02