margin基礎(chǔ)
在DIV+CSS布局網(wǎng)頁(yè)的時(shí)候,margin
是很常用的一個(gè)屬性瘤旨。作用是設(shè)置元素的外邊距。不要問(wèn)我什么叫外邊距的問(wèn)題,你可以想象一下如果心中的女神突然出現(xiàn)在自己面前把夸,我想在第一時(shí)間除了臉紅、心跳嘴巴干之外铭污,不會(huì)有別的反應(yīng)恋日。這個(gè)時(shí)候你敢不敢去牽她的手?如果你說(shuō)你敢那我只能會(huì)以膜拜的神情嘹狞。對(duì)于這種優(yōu)先下半身思考的模式直接獻(xiàn)上我的膝蓋了岂膳。
說(shuō)遠(yuǎn)了,繼續(xù)繼續(xù)~ 這個(gè)時(shí)候你肯定和她身體有一定距離磅网,這個(gè)就叫邊距谈截。隨著雙方理解和信任的增加,她對(duì)你牽手kiss之類(lèi)的舉動(dòng)已經(jīng)不再抗拒,這個(gè)時(shí)候你的手或者嘴與對(duì)方親密接觸的地方邊距就為零簸喂,很好理解吧毙死。什么?你說(shuō)邊距為負(fù)是什么情況喻鳄?嘿嘿嘿~ 自己想扼倘!
咳咳~ 我們繼續(xù)……由盒模型能看出來(lái)margin
有四個(gè)方向margin-top
、margin-right
除呵、margin-bottom
再菊、margin-left
。既是分別設(shè)置上方外邊距颜曾、右邊外邊距纠拔、下方外邊距、左邊的外邊距泛豪。例如:margin-right:10px;
就是設(shè)置上方外邊距是10個(gè)像素绿语。呵呵,順嘴提一下候址,margin
是可以設(shè)置負(fù)值的吕粹。
我喜歡margin
因?yàn)樗强梢院?jiǎn)寫(xiě)的屬性,操作起來(lái)特別省代碼岗仑。具體用法 margin:5px 10px 15px 2px;
四個(gè)值的排列順序是上匹耕、右、下荠雕、左稳其。具體代碼解釋是分別設(shè)置了上邊距5px
、右邊距10px
炸卑、下邊距15px
既鞠、左邊距2px
。
根據(jù)情況不同盖文,簡(jiǎn)寫(xiě)的方式也不同嘱蛋。例如上下邊距相等都為20px
,左右邊距同時(shí)為10px
五续,就可以簡(jiǎn)寫(xiě)為margin:20px 10px;
第一個(gè)20px
代表垂直方向,第二個(gè)10px
代表水平方向洒敏。如果垂直方向不相等,水平方向相等疙驾。就可以寫(xiě)成margin:5px 10px 2px;
最后一個(gè)左邊的值和右邊相等可以省略不寫(xiě)凶伙。如果上下相等,左右不相等它碎,就只能乖乖的寫(xiě)齊四個(gè)數(shù)函荣。
所有的瀏覽器都支持margin
屬性显押,需要一提的是任何版本的IE瀏覽器都不支持margin:inherit;
為什么不能繼承呢?我想和margin為負(fù)有關(guān)系傻挂,嗯一定是這樣的乘碑。爹對(duì)媽能做的事情有些兒子還真不能做。哈哈哈~繼承么踊谋,試想啊蝉仇,給一個(gè)<div>
設(shè)置了margin-top:10px;
里面的子元素<p>
也是margin-top:10px
了么旋讹?另外提一下<p>
的默認(rèn)margin:16px 0;
殖蚕。小tips:CSS中零值可以不寫(xiě)單位,直接寫(xiě)0就行了沉迹。
折疊現(xiàn)象
margin的折疊或者叫做margin的塌陷睦疫,有一個(gè)更專(zhuān)業(yè)的術(shù)語(yǔ)來(lái)稱(chēng)呼這種現(xiàn)象——collapsing margins。舉個(gè)例子來(lái)說(shuō)明一下鞭呕。比如給<ul>
下面的<li>
設(shè)置margin:5px 10px;
含義是垂直方向各是5px
蛤育,水平方向各是10px;
在沒(méi)有做浮動(dòng)的情況下多個(gè)<li>
垂直排列。
那么<li>
之間的間距是多少呢葫松?你可能會(huì)說(shuō)瓦糕,這還不簡(jiǎn)單,垂直方向上下都是5px
腋么,每一個(gè)<li>
的下邊距和它下方<li>
的上邊距相加不就是兩者的間距啊咕娄,這個(gè)問(wèn)題的答案是10px
。嘿嘿珊擂,不懷好意的笑完圣勒,我再告訴你10px
的答案是錯(cuò)的。瀏覽器實(shí)際渲染的間隔結(jié)果展現(xiàn)出來(lái)的是5px
摧扇。為啥是5px
不是10px
?我回答你圣贸,這種現(xiàn)象好似女朋友告訴你,讓你離她遠(yuǎn)點(diǎn)扛稽,我估計(jì)沒(méi)有人真的會(huì)去離她遠(yuǎn)點(diǎn)吁峻,大多數(shù)人都是會(huì)上去抱抱哄一哄≡谡牛看下面的GIF動(dòng)圖锡搜,會(huì)比較直觀一些。
上述的只是折疊現(xiàn)象之一瞧掺,再看下其他的「停現(xiàn)在有兩個(gè)<div class="one">
和<div class="two">
,兩者是嵌套關(guān)系辟狈。one嵌套two,如果在one設(shè)置margin-top:30px;
在two設(shè)置margin-top:20px;
會(huì)是什么結(jié)果肠缔?布拉布拉布拉~
如果你腦海中構(gòu)建的渲染結(jié)果和上圖一樣夏跷,那么恭喜~又錯(cuò)了!其實(shí)真實(shí)的渲染結(jié)果是:
WHATC魑础槽华?什么情況?又來(lái)趟妥?一句“知道真相的我眼淚流下來(lái)”表達(dá)心中的感慨猫态。我不知道第一次面對(duì)這種現(xiàn)象的時(shí)候你的狀態(tài)是什么,反正剛開(kāi)始接觸前端的時(shí)候披摄,我是被這個(gè)折疊問(wèn)題折磨的不要不要的亲雪,甚至已經(jīng)開(kāi)始懷疑人生。
刨根問(wèn)底
稍安勿躁疚膊,抱著探根問(wèn)底的精神义辕,認(rèn)真查資料、查文檔才能讓自己的技術(shù)有質(zhì)的飛越寓盗。為了不讓“自己知其然不知其所以然”灌砖,找了一圈資料才發(fā)現(xiàn)其實(shí)早在CSS1.0的時(shí)代官方就給出過(guò)這種現(xiàn)象的說(shuō)明用爪。
原文:The width of the margin on non-floating block-level elements specifies the minimum distance to the edges of surrounding boxes. Two or more adjoining vertical margins (i.e., with no border, padding or content between them) are collapsed to use the maximum of the margin values. In most cases, after collapsing the vertical margins the result is visually more pleasing and closer to what the designer expects.
翻譯:外邊距用來(lái)指定非浮動(dòng)元素與其周?chē)凶舆吘壍淖钚【嚯x秀菱。兩個(gè)或兩個(gè)以上的相鄰的垂直外邊距會(huì)被折疊并使用它們之間最大的那個(gè)外邊距值。多數(shù)情況下侥猬,折疊垂直外邊距可以在視覺(jué)上顯得更美觀善炫,也更貼近設(shè)計(jì)師的預(yù)期撩幽。
為毛線這幫CSS的設(shè)計(jì)者們要搞出個(gè)這個(gè)飛機(jī)來(lái)折磨技術(shù)人員?想了半天終于釋?xiě)蚜讼浚驗(yàn)镃SS的基本模型是排版摸航,現(xiàn)在的前端工程師使用CSS主要是用來(lái)布局而不是文字排版。
CSS并沒(méi)有對(duì)布局和排版進(jìn)行界定區(qū)別舅桩。而collapsing margins存在的初衷是解決文字排版段落間的間隔而存在的特性酱虎,所以collapsing margins才會(huì)給設(shè)計(jì)者們帶來(lái)巨大的困惑。再回到上面看第一個(gè)關(guān)于<li>
的例子那里擂涛,看圖片中那種等邊距設(shè)計(jì)在視覺(jué)效果看上去是不是顯得很協(xié)調(diào)读串?這就是“更貼近設(shè)計(jì)師的預(yù)期”的含義。
上段文字并不能很好的解釋第二個(gè)嵌套的例子中的現(xiàn)象撒妈。第二種情況看上去并不是十分符合collapsing margins的定義恢暖。造成現(xiàn)象出現(xiàn)的原因其實(shí)是由另一個(gè)CSS特性決定的——即對(duì)于有塊級(jí)子元素的父級(jí)元素高度的計(jì)算方式。如果父元素沒(méi)有垂直邊框(border
)和填充(padding
),那其高度就是其子元素頂部和底部邊框邊緣之間的距離狰右,也就是子元素的height
屬性杰捂。所以子元素設(shè)置margin
才不會(huì)在離開(kāi)父級(jí)元素的上邊。其實(shí)關(guān)于嵌套<div>例子中的的圖片畫(huà)的不是很準(zhǔn)確棋蚌,但是這樣畫(huà)才能更直觀突出問(wèn)題所在也更美觀嫁佳,跪求不噴挨队。
做學(xué)問(wèn)要“存不疑”,要想搞清楚還是要仔細(xì)看下官方關(guān)于collapsing margins的解釋
In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.
翻譯:在CSS中蒿往,兩個(gè)或兩個(gè)以上的塊元素(可能是兄弟盛垦,也可能不是)之間的相鄰?fù)膺吘嗫梢员缓喜⒊梢粋€(gè)單獨(dú)的外邊距。通過(guò)此方式合并的外邊距被稱(chēng)為折疊瓤漏,且產(chǎn)生的已合并的外邊距被稱(chēng)為折疊外邊距腾夯。
問(wèn)題來(lái)了,什么叫相鄰的蔬充?官方給出了一大堆文字蝶俱,我英語(yǔ)水平差到?jīng)]朋友,還是直接說(shuō)明吧娃惯,處于同一個(gè)塊級(jí)上下文中的塊元素跷乐,沒(méi)有行框肥败、沒(méi)有間隙趾浅、沒(méi)有內(nèi)邊距和邊框隔開(kāi)它們,這樣的元素垂直邊緣毗鄰馒稍,則稱(chēng)之為相鄰皿哨。仔細(xì)觀察的你肯定會(huì)發(fā)現(xiàn)我上面的兩個(gè)例子中都是在垂直方向上產(chǎn)生的折疊,我想說(shuō)是的纽谒,折疊現(xiàn)象只會(huì)在垂直方向上產(chǎn)生证膨,在水平方向的margin是不會(huì)出現(xiàn)折疊的。
垂直方向的margin
會(huì)出現(xiàn)折疊鼓黔,又是相鄰元素央勒。那么垂直相鄰元素是啥?我蹩腳的英語(yǔ)又要上場(chǎng)了澳化。
- both belong to in-flow block-level boxes that participate in the same block formatting context
- no line boxes, no clearance, no padding and no border separate them (Note that certain zero-height line boxes (see 9.4.2) are ignored for this purpose.)
- both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
- top margin of a box and top margin of its first in-flow child.
- bottom margin of box and top margin of its next in-flow following sibling.
- bottom margin of a last in-flow child and bottom margin of its parent if the parent has ‘a(chǎn)uto’ computed height.
- op and bottom margins of a box that does not establish a new block formatting context and that has zero computed ‘min-height’, zero or ‘a(chǎn)uto’ computed ‘height’, and no in-flow children
翻譯:
- 元素的上外邊距和其屬于常規(guī)流中的第一個(gè)子元素的上外邊距崔步。
- 元素的下外邊距和其屬于常規(guī)流中的下一個(gè)兄弟元素的上外邊距。
- 屬于常規(guī)流中的最后一個(gè)元素的下外邊距和其父元素的下外邊距缎谷,如果其父元素的高度計(jì)算值為 auto井濒。
- 元素的上、下外邊距列林,如果該元素沒(méi)有建立新的塊級(jí)格式上下文瑞你,且 min-height 的計(jì)算值為零、height 的計(jì)算值為零或 auto希痴、且沒(méi)有屬于常規(guī)流中的子元素者甲。
呵呵,英語(yǔ)實(shí)在太差了砌创,講究不了信達(dá)雅了虏缸。直接百度翻譯搞定甥厦。將就著看吧,上述文字的最直觀的收獲是說(shuō)得是發(fā)生margin
折疊的元素不一定是兄弟關(guān)系寇钉,也能是父子或祖先的關(guān)系刀疙。這就能解釋為什么上文中<div>
嵌套也是折疊現(xiàn)象中的一種。后兩段包含height:auto;
的兩句話扫倡,也表明了那個(gè)高度的計(jì)算方式的根源出處谦秧。
這一part基本可以pass了,該是做總結(jié)的時(shí)候了撵溃。綜合上述官方的說(shuō)明可以得出幾點(diǎn)很有用的信息疚鲤。
- 根元素不會(huì)發(fā)生折疊;
- 塊級(jí)元素才會(huì)有折疊缘挑;
- 發(fā)生折疊需要是相鄰的非浮動(dòng)元素集歇;
- 折疊發(fā)生在垂直外邊距上,即
margin-top/margin-bottom
语淘;- 含有邊框诲宇、填充距不會(huì)有折疊。
- 折疊后取其中最大的那個(gè)margin值作為最終值惶翻;
關(guān)于最后一個(gè)折疊后margin
的取值問(wèn)題姑蓝,還要多兩句嘴。由于margin
可以取負(fù)值,所以margin
折疊的最終取值會(huì)三種情況發(fā)生吕粗。正正纺荧、正負(fù)、負(fù)負(fù)颅筋。就取值問(wèn)題整了個(gè)列表方便查看記憶宙暇。
- 參與折疊計(jì)算的都是正數(shù)的情況下,取最大值為折疊后的最終值议泵。
- 參與折疊計(jì)算的都是負(fù)數(shù)的情況下占贫,取絕對(duì)值最大的值為折疊后的最終值。
- 參與折疊計(jì)算的有正數(shù)也有負(fù)數(shù)的情況下,先取出負(fù)值中絕對(duì)值最大的值然后和正數(shù)中最大的數(shù)相加的結(jié)果就是折疊后的最終值肢簿。
避免折疊
折疊的來(lái)龍去脈已經(jīng)被我們探究的差不多了靶剑,那么如何在日常工作中怎么才能避免被折疊現(xiàn)象給坑了?我們先來(lái)看看折疊發(fā)生的條件池充,然后反其道而行之就能避免遭遇折疊了桩引。
- margin 折疊元素只發(fā)生在塊元素上;
- 浮動(dòng)元素不與其他元素 margin 折疊收夸;
- 定義了屬性overflow且值不為visible的塊元素坑匠,不與它的子元素發(fā)生margin 折疊;
- 絕對(duì)定位元素的 margin 不與任何 margin 發(fā)生折疊卧惜。
- 特殊:根元素的 margin 不與其它任何 margin 發(fā)生折疊厘灼;
- 如果常規(guī)流中的一個(gè)塊元素沒(méi)有 border-top夹纫、padding-top,且其第一個(gè)浮動(dòng)的塊級(jí)子元素沒(méi)有間隙设凹,則該元素的上外邊距會(huì)與其常規(guī)流中的第一個(gè)塊級(jí)子元素的上外邊距折疊舰讹。
- 如果一個(gè)元素的 min-height 屬性為0,且沒(méi)有上或下邊框以及上或下內(nèi)邊距闪朱,且 height 為0或者 auto月匣,且不包含行框,且其屬于常規(guī)流的所有孩子的外邊距都折疊了奋姿,則折疊其外邊距锄开。
好吧,條件還挺多称诗。不過(guò)難不倒膽大心細(xì)臉皮厚的我們萍悴。按照一般常理是條件越多,避規(guī)的手段也就越多寓免。如此看來(lái)能避規(guī)折疊的手段應(yīng)該不會(huì)少了癣诱,其實(shí)在這么奇葩條件下我們都能遇見(jiàn)折疊,也算運(yùn)氣了再榄。
避規(guī)折疊狡刘,首先就是修改塊級(jí)元素變?yōu)榉菈K級(jí)元素享潜,如果不清楚塊級(jí)元素和行內(nèi)元素的區(qū)別困鸥,出門(mén)左轉(zhuǎn)《行內(nèi)元素和塊級(jí)元素的那些事兒》有詳細(xì)說(shuō)明。還能讓元素浮動(dòng)來(lái)避規(guī)折疊剑按。還能設(shè)置border
疾就、絕對(duì)定位、設(shè)置overflow:hidden;
看具體情況來(lái)用不同的方法艺蝴。個(gè)人用的最多的就是overflow:hidden;
因?yàn)樵O(shè)置border
多出來(lái)的像素會(huì)讓布局上有些小差異猬腰,設(shè)置絕對(duì)定位會(huì)讓元素脫離文本流。
好了,洋洋灑灑的寫(xiě)了這么多猜敢,margin
的折疊你也許已經(jīng)弄的很明白了姑荷,以后的工作或?qū)W習(xí)中遇到這個(gè)問(wèn)題應(yīng)該能夠得心應(yīng)手、收放自如缩擂、信手拈來(lái)了鼠冕。
關(guān)鍵點(diǎn)補(bǔ)充
CSS2及后續(xù)的規(guī)范中,將margin
折疊描述得更為詳盡了胯盯。例如在水平書(shū)寫(xiě)模式下懈费,發(fā)生margin
折疊的是垂直方向,即margin-top/margin-bottom
博脑,在垂直書(shū)寫(xiě)模式下憎乙,margin
折疊發(fā)生在水平方向上票罐,即margin-right/margin-left
。
你問(wèn)書(shū)寫(xiě)方式怎么改泞边?writing-mode
啊该押,它有兩個(gè)主要參數(shù)lr-tb
: 左-右,上-下阵谚。即水平逐行書(shū)寫(xiě)沈善,這個(gè)也是現(xiàn)代人的書(shū)寫(xiě)習(xí)慣;tb-rl
: 上-下椭蹄,右-左闻牡。即從上到下書(shū)寫(xiě),寫(xiě)滿(mǎn)一列绳矩,向左側(cè)折列罩润。和中國(guó)古代書(shū)寫(xiě)方式一樣。如果修改了書(shū)寫(xiě)方向變成垂直了翼馆,那么collapsing margins就會(huì)在水平方向發(fā)生割以,而不會(huì)在垂直方向上出現(xiàn)。
先別高興的說(shuō)应媚,我剛才寫(xiě)出來(lái)writing-mode
的值什么lr-tb
严沥、tb-rl
啊,其實(shí)是老IE瀏覽器的語(yǔ)法中姜。有多老消玄?IE7版本都能支持這兩個(gè)值,夠古老了吧丢胚。先提老語(yǔ)法是想強(qiáng)調(diào)writing-mode
屬性不是多么高大上新的東西翩瓜,只不過(guò)我們用的不多所以才不熟悉。現(xiàn)在我們?cè)趺磿?shū)寫(xiě)屬性的值呢携龟?很簡(jiǎn)單:
writing-mode: horizontal-tb; /* 默認(rèn)值 */
writing-mode: vertical-rl; /*垂直書(shū)寫(xiě)兔跌,從右向左閱讀(和漢字古文一樣)*/
writing-mode: vertical-lr; /*垂直書(shū)寫(xiě),從右向左閱讀(只是方向發(fā)生變化)*/
上個(gè)圖峡蟋,說(shuō)明問(wèn)題~~
最后我寫(xiě)了一個(gè)綜合性的demo,來(lái)全面的展示下margin
折疊的尿性坟桅。包括修改書(shū)寫(xiě)方向的示例。想看demo的就>>>猛戳這里<<<