原作者:doyoe
原文鏈接: http://blog.doyoe.com/2013/12/20/css/margin%E7%B3%BB%E5%88%97%E4%B9%8Bbug%E5%B7%A1%E6%BC%94%EF%BC%88%E4%B8%89%EF%BC%89/
你會(huì)猛然覺得,這是正解啊,因?yàn)?button
或者 input type button類型
的元素是 inline-level
的。
不對(duì)啊,button
應(yīng)該是 inline
的吧?哦,可能是 inline-block
?
在這之前,我們似乎要先明確一些基礎(chǔ)知識(shí)。
要知道 inline-level
元素并不等于 inline
元素,也就是說 行內(nèi)級(jí)元素
與 行內(nèi)元素
是兩個(gè)不同的概念。
inline-level
元素包含 display
值為:以上情況時(shí),元素可被稱之為 inline-level
元素,但不都是 inline
元素。
block-level
指的是 display
值為 block
的元素嗎?我知道不少人一直有這樣的認(rèn)知,不過這不完全準(zhǔn)確。
block-level
元素包含 display
值為:有如上情況時(shí)的元素均被稱之為 block-level
元素。同時(shí) block-level
和 block
也不是同一個(gè)概念,所以如果你認(rèn)為 display
值為 list-item
的 li
不是 塊級(jí)元素
,那就錯(cuò)了。
看到這里,你對(duì) 塊級(jí)元素
,塊元素
,行內(nèi)級(jí)元素
,行內(nèi)元素
這個(gè)4個(gè)概念,應(yīng)該已經(jīng)有了比較清晰的了解?
position
值為非 static
和 relative
之外的值時(shí),margin-right/left auto 的計(jì)算值為0;float
值為非 none
之外的值時(shí),margin-right/left auto 的計(jì)算值為0;計(jì)算值為0,即說明其應(yīng)用使用值的意圖失敗。所以在有如上情形的場(chǎng)景中,都無法使用 auto
來實(shí)現(xiàn)水平居中。同時(shí)也說明了,只有normal flow
的 block-level
才能應(yīng)用 margin keyword auto。
這顯然不行。準(zhǔn)確的說:margin可以應(yīng)用在除某些table-*元素和某些行內(nèi)元素之外的所有元素上。
除了 display
值為以上3種之外的 table系 元素,都不能應(yīng)用 margin
,比如:th, td。
我之前面試的時(shí)候常會(huì)問候選人,行內(nèi)元素不能設(shè)置寬高對(duì)嗎?大部分人會(huì)告訴我說是;然后我又會(huì)問,那為什么 img
元素可以設(shè)置寬高呢?有人會(huì)告訴我,因?yàn)?img
是個(gè)特殊的元素?接著我又會(huì)問題,img
是如何特殊的?然后,然后就沒然后了,因?yàn)闆]聲音了。
恩,img
確實(shí)是個(gè)特殊的元素。它特殊在哪里?它的特殊就在于它是一個(gè)行內(nèi)置換元素。
所有的置換元素都可以設(shè)置 margin
屬性,并且可以設(shè)置寬高,這就是為什么 img
是行內(nèi)元素卻可以設(shè)置 width
和 height
。
一個(gè)元素?fù)碛袃?nèi)在的二維屬性,其寬高屬性受外部資源影響,默認(rèn)擁有CSS格式,這樣的元素被稱為置換元素。
意思就是說置換元素的寬高不完全由CSS決定,還受其自身內(nèi)容和外部資源所影響。
舉個(gè)例子來說,仍然說 img
元素吧,你會(huì)發(fā)現(xiàn),如果你 src
進(jìn)來不同尺寸的資源,那么在 viewport
上顯示的圖片寬高也是不同的,也就是說 img
元素的寬高會(huì)受外部資源影響。
再說說 input
元素,隨便在頁面上扔一個(gè)input,你都能發(fā)現(xiàn)它擁有一個(gè)默認(rèn)的寬高,這就是它所具有的內(nèi)在二維寬高屬性,并且該類元素會(huì)受UA影響,不同UA下所呈現(xiàn)外觀會(huì)有不同。
img, object, button, input, textarea, select等
什么是非置換元素?除了置換元素之外的元素,我想將這樣的元素稱之為非置換元素是沒有大礙的。
那么行內(nèi)非置換元素真的無法設(shè)置 margin 嗎?我想在工作中你一定碰到過很多這樣的場(chǎng)景,給一個(gè) a
或者 span
定義間隙。這時(shí)我們寫:
span{margin:5px 10px;}
結(jié)果發(fā)現(xiàn) span
的水平方向上的 margin
定義生效了,但垂直方向上的 margin
定義卻沒被應(yīng)用。
是的,這就是行內(nèi)非置換元素使用 margin
時(shí)的表征,所以對(duì)各種特性的理解,在讓自己的代碼更有效上是大有裨益的。
我們本來是想說IE8按鈕margin auto居中失效Bug的,扯了不少題外話。
我們知道 margin keyword auto
不能應(yīng)用在處于常規(guī)流中的 block-level
之外的元素上,所以我有這樣的一段代碼:
button{display:block;margin:auto;}
<div id="demo">
<button>按鈕</button>
</div>
恩,我們將 button
顯式的轉(zhuǎn)換為了 block
,同時(shí)我們知道 button
作為置換元素,本身具備內(nèi)在寬高,也就是說這時(shí),我只需要加上 margin:auto
,該按鈕就應(yīng)該在其包含塊里水平居中。
是的,所有瀏覽器都和預(yù)期是一樣,實(shí)現(xiàn)了水平居中,但是卻出現(xiàn)了奇葩的IE8,完全無效,甚至不如原始社會(huì)的IE6。來看看示例 DEMO1
:IE8按鈕margin auto居中失效Bug
通過以上例子,你有沒有突然感覺到,如果要讓一個(gè)置換元素在包含塊中水平居中,出乎預(yù)料的簡(jiǎn)單,只需要 display:block;margin:auto;
即可。
令人意外的是,只有 button
和 input type
為 button
相關(guān)元素的時(shí)候,在IE8中才會(huì)水平居中失效;如: input type text
或 img
時(shí),margin keyword auto
運(yùn)作正常。
更多建議: