曾幾什麼時候,display:inline-block 已經深刻「大街小巷」,隨處可見 「display:inline-block; *display:inline; *zoom:1; 」這樣的代碼。現在現代瀏覽器已經全面支持這個屬性值了,上面的代碼是爲了兼容 IE六、7而已。那麼你真的瞭解 inline-block 了嗎?本文將帶你深刻剖析該屬性值的前世此生,讓你更好的理解和運用 inline-block。(本文約定 display:inline-block 簡寫爲 inline-block)css
開篇咱們來看幾個問題:html
IE六、7 真的不支持 display:inline-block 嗎?web
display:inline-block 後的元素爲何會產生水平空隙,這真的是 bug 嗎?chrome
如何更好的解決 display:inline-block 元素間產生的水平空隙?api
也許有人問你爲什麼要寫「 display:inline-block; *display:inline; *zoom:1; 」 來兼容 IE六、7 時,你會立馬答道:由於 IE六、7 不支持 display:inline-block 唄!不知道什麼時候起,慣性思惟給開發者帶來了這樣一個可怕的概念。萬物都是辯證的,當你寫下這些的時候,可曾懷疑過大衆觀點真的可靠嗎?也許你認爲這些可有可無,實現效果就好。可是若是不能理解每一個屬性或屬性值的根本,你將永遠沒法全面的瞭解它,人云亦云只會讓你淺嘗輒止,止步不前。那麼這裏就涉及到所謂的 「CSS 學習瓶頸」的問題了,這個問題張鑫旭《說說CSS 學習中的瓶頸》一文有詳細闡述,雖然部分觀點我不是很贊同,可是中心思想仍是很值得思考的。文中有幾個不錯的問題這裏也列舉出來供你們觀摩:瀏覽器
line-height:150% 和 line-height:1.5 的區別是?app
float 爲什麼會讓外部容器高度塌陷?這是 bug?ide
vertical-align 的表現爲什麼在IE7, IE8, IE9 下表現不盡相同?其中的渲染機制是?wordpress
好了,回到 inline-block 的認知的問題,個人觀點是:佈局
IE 從 5.5 開始就已經支持 display:inline-block 了,只是支持的並非那麼完善。
在 msdn 微軟開發者社區,找到了 IE 從5.5 開始支持 inline-block 的證據:
The inline-block value is supported starting with Internet Explorer 5.5. You can use this value to give an object a layout without specifying the object's height or width.
這裏明確指出:從 IE5.5 開始支持 inline-block。
連接:http://msdn.microsoft.com/zh-cn/library/ie/ms530751(v=vs.85).aspx
那麼既然 IE5.5 開始就已經支持了 inline-block,爲什麼咱們還要寫那麼一坨 CSS 呢?同時咱們知道 IE六、7 中 display:inline-block 是能夠觸發 hasLayout 的,觸發了 hasLayout 的元素表現出來的特徵就是一個獨立的矩形容器,能夠設置寬高並且不受外部元素的影響,相似於現代瀏覽器中的 Block formatting contexts (塊級格式化上下文)的概念。
下面來作一個詳細的測試,分別看看 IE6 中 inline 元素和 block 元素的表現:
1)inline 元素 display:inline-block
IE6 中截圖以下:
.dib-inline, .dib-block {
width:100px;
height:30px;
line-height:30px;
text-align:center;
}
.dib-inline {
display:inline-block;
}
測試代表:IE6 中 inline 元素只要觸發了 hasLayout 其表現就相似於 inline-block,這裏設置 display:inline-block; 或者 zoom:1; 等其餘屬性值能夠觸發 hasLayout ,表現出來是同樣的。
2)block 元素 display:inline-block
IE6 中截圖以下:
.dib-inline, .dib-block {
width:100px;
height:30px;
line-height:30px;
text-align:center;
}
.dib-block{
display:inline-block;
}
測試代表:IE6 中 block 元素即便觸發了 hasLayout 也不能具備 inline-block 元素不換行的特性。想要 block 元素支持 inline-block 元素的特性,咱們能夠這樣作:
.dib-block {
display:inline;
zoom:1;
}
首先讓 block 元素轉化爲 inline 元素,強制其不換行;而後經過 zoom:1 觸發 hasLayout,使其能夠設置寬高。修復後的 截圖以下:
3)結合現代瀏覽器
綜上,現代瀏覽器都支持 display:inline-block ,IE六、7 inline 元素也能夠達到一樣的效果,IE六、7 block 元素須要設置 display:inline; zoom:1; 它們結合在一塊兒即是:
display:inline-block; /* 現代瀏覽器 +IE六、7 inline 元素 */
*display:inline; /* IE六、7 block 元素 */
*zoom:1;
爲了避免讓支持 CSS2.1 inline-block 的瀏覽器 重置爲 inline,咱們針對 IE六、7 作一個 hack。因爲現代瀏覽器也開始支持 zoom 屬性,這裏只是但願 IE六、7 中生效,因此仍是 hack 一下比較合適。至此產生了咱們熟悉的兼容各個瀏覽器的 inline-block 寫法。
小結:IE六、7 並非不支持 inline-block,只是 block 元素須要作一些處理來達到 inline-block 的效果。
說了不少,或許不少朋友還不是太明白到底什麼是 inline-block?W3C 在 CSS2.1 The 'display' property 中描述以下:
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.
大體意思就是:inline-block 後的元素建立了一個行級的塊容器,該元素內部(內容)被格式化成一個塊元素,同時元素自己則被格式化成一個行內元素。
直白一點的意思就是:inline-block 的元素既具備 block 元素能夠設置寬高的特性,同時又具備 inline 元素默認不換行的特性。固然不只僅是這些特性,好比 inline-block 元素也能夠設置 vertical-align 屬性。簡而言之:
inline-block 後的元素就是一個格式化爲行內元素的塊容器( Block container )
怎麼樣?聽起來還不錯吧!
前面已經證實了 IE 5.5 開始就支持了 inline-block,那麼 IE5.5 是何時發佈的呢?話說當年網景與 IE 大戰,IE5.5 那是何等的風騷……(好吧,此處略去十頁)。從維基百科的資料來看,IE5.5 beta1 的發佈時間是:1999年12月,最終版本是 2000年7月。那麼 W3C 標準中是什麼時候纔出現 inline-block 這個值的呢?
在 CSS1 規範中,「display」的值僅包括: block | inline | list-item | none 。CSS2.1中才添加了 inline-block 屬性值。一絲繼續舔着手指,用那苦逼的英語水平終於翻到了這份草案:http://www.w3.org/TR/2002/WD-CSS21-20020802/visuren.html#display-prop, 這份草案的日期是 2002年8月2日,納尼!!!原來咱們糾結了半天的 inline-block , IE5.5 至少提早兩年就提出來了啊!難道是微軟給 W3C 提議後,CSS 2.1才加入的?(不過我看到 W3C 官網有一個關因而否增長 inline-block 的投票)好吧這個問題也許有一天 IE 某個開發者寫《 IE回憶錄》的時候咱們才能瞭解到其中的內幕。若是找到更早關於 inline-block 的 CSS草案,也麻煩告知一絲一聲。好吧,若是你還不相信,打微軟官方電話問問吧 800-820-3800(不是 DHC 哦!)。
原來咱們一直討論的 inline-block 在 IE 六、7中和 CSS2.1 中的(現代瀏覽器所支持的) inline-block 上壓根不是一個東東嘛,IE六、7 中的 inline-block 更像是 IE 的私有屬性值,他們自己就不具備可比性。簡單、絕對的認爲 IE六、7 不支持 inline-block 比如一葉障目,看到前面,卻看不到後面,太過於片面。誠然,IE六、7 的 hasLayout 給咱們帶來了不少麻煩,可是不得不認可微軟的 IE 在網頁多語言文本混排上的先進性,尤爲是 CJK 文字和西文的混排,超越其餘瀏覽器至少5年。
總結:
IE5.5 後開始支持 inline-block, 可是它所支持的 inline-block 不能等同於 CSS2.1 中的 inline-block,由於 IE5.5 比 CSS2.1 更早提出 inline-block 的概念並做爲所謂的「私有屬性值」使用,因此兩者表現出來的效果是不徹底一致。
IE 5.五、六、7 、8(Q)中 block 元素對 inline-block 支持不完整,若是要達到相似的效果,須要先設置爲 display:inline,而後使用 zoom:1 等觸發 hasLayout。
IE 5.五、六、7 、8(Q)中 inline 元素欲達到 inline-block 的效果只需直接設置此屬性值或使用 zoom:1 等都可。
這麼一個神奇的屬性,爲什麼你們一直避而遠之呢?這恐怕還得從 inline-block 元素之間產生的水平空隙(間隙)提及吧。
現代瀏覽器中 inline 和 block 元素 display:inline-block 後均會產生水平空隙;
IE六、7,IE8(Q)模擬 display:inline-block 後分兩種狀況:
IE六、7,IE8(Q)中:inline 元素會產生空隙,block 元素不會產生空隙。
看看 inline 元素默認的表現狀況如何?原來默認就有空隙存在!它們是誰?是空白符(white space)!
W3C 9.1 White space 中規定如下元素屬於空白符(white space):
ASCII 空格 ( )
ASCII 製表符 (	)
ASCII 換頁符 ()
零寬度空格 (​)「這個在閉合浮動中也有運用到」
9.3.2 Controlling line breaks 中進一步闡述:
A line break is defined to be a carriage return (
), a line feed (
), or a carriage return/line feed pair. All line breaks constitute white space.
For more information about SGML's specification of line breaks, please consult the notes on line breaks in the appendix.
折行被定義爲一個回車符(
),一個換行符 line feed (
),或者一個回車、換行的組合。全部的折行構成了空白符。
有關 SGML 規範中折行的更多信息,請參閱附錄中關於折行的註釋。
一般狀況下,對於多個連續的空白符(空格,換行符,回車符等),瀏覽器會將他們合併爲一個空白符。CSS 中由 white-space 這個屬性來控制:
white-space:normal | pre | nowrap | pre-wrap | pre-line
默認值:normal
normal:默認處理方式。
pre:用等寬字體顯示預先格式化的文本,不合並文字間的空白距離,當文字超出邊界時不換行。可查閱 pre 對象
nowrap:強制在同一行內顯示全部文本,直到文本結束或者遭遇 br 對象。
pre-wrap:用等寬字體顯示預先格式化的文本,不合並文字間的空白距離,當文字碰到邊界時發生換行。
pre-line:保持文本的換行,不保留文字間的空白距離,當文字碰到邊界時發生換行。
注:IE7及更早瀏覽器不支持 CSS2.1 新增的 pre-wrap | pre-line。
因此這並非 inline-block 後產生的 bug,而是由於 inline-block 具備 inline 元素固有的特性。那麼爲什麼 IE六、7 block 元素沒有產生空隙呢?其實前面也提到了 IE 的 hasLayout,具備獨立性,因此產生 hasLayout 的元素之間表現出來互不影響,這也再次代表 IE六、7 中的 inline-block 不能等同於 CSS2.1 中的 inline-block。若是非要說是有 bug, IE六、7 block 元素 inline-block 後不產生空隙纔是 bug。
測試代表刪除換行符後,inline 元素間的空隙就「消失」了:
爲了讓各個瀏覽器表現一致,更好的還原視覺設計搞,不少時候咱們須要去掉 inline-block 產生的空隙。
上一節中咱們已經知道產生空隙的根本性緣由是:
HTML 中的換行符、空格符、製表符等產生了空白符,而這些歸根結底都是字符,那麼它們的大小都是受 font-size 來控制的,字體大小直接致使 inline 或者 inline-block 後元素之間空隙的大小,把 inline-block 元素間的空隙認爲老是某個固定大小是錯誤的。
很清楚的看到,當 font-size:0 的時候元素間的空隙都爲0了,或許到這裏你會感到很欣喜了,原來掌握的根本性緣由這麼簡單就搞定了啊!
然,理想是豐滿的,現實是骨感的。
大部分瀏覽器是支持 font-size:0 的。很明顯,咱們要和 IE 六、7 這兩個妖孽進行一番戰鬥。
font-size:0 的支持狀況
1)Chrome
低版本的 chrome 瀏覽器爲了避免讓文字太小不利於閱讀,默認是不支持 font-size:0 的,還好咱們有 -webkit-text-size-adjust 這個私有屬性來控制,當設爲 none 時就支持字體大小爲 0 了。我已經記不清楚 chrome 從哪一個版本開始支持 font-size:0 了,反正我用 chrome 19 是支持了(有知道的朋友,煩請告訴一絲一聲,最好有官方更新說明)。可是,-webkit-text-size-adjust:none; 會直接致使頁面文字沒法縮放,這對於用戶來講顯然是不友好的。因此-webkit-text-size-adjust:none; 必定要慎用,確保使用的地方沒有大面積的文字。
-webkit-text-size-adjust:none 的使用場景實例參閱:http://vip.etao.com/
2)Safari
Safari 5 依舊不支持 font-size:0 ,不過相信這些瀏覽器廠商都意識到了這個問題,在 Mac 平臺最新的 Safari 6 已經很好的支持 font-size:0 了。
3)Firefox,Opera
經測試,Firefox12,Opera 10 ,此次表現不錯,支持 font-size:0 。
4)IE
IE8 以上支持 font-size:0;
IE六、7 inline 元素 inline-block 後設置 font-size:0 始終有 1px 的空隙。
是否是一會兒又開始頭疼了?不要緊,讓咱們請出 letter-spacing 和 word-spacing 二位大神。既然空白符也是字符,那麼二位大神確定是能夠搞定它們的。
letter-spacing : normal | length (檢索或設置對象中的文字之間的間隔)
word-spacing : normal | length(檢索或設置對象中的單詞之間插入的空隔)
normal: 默認間隔
length: 用長度值指定間隔,容許爲負值。
還等什麼,咱們趕忙試試吧:
第一步:使用 font-size:0
經測試發現,chrome、firefox、IE8+、opera,inline 或 block 元素都沒有空隙了;
IE六、七、8(Q),inline 元素 inline-block 後始終存在 1px 左右的空隙。
第二步:處理 Safari 不支持 font-size:0 的問題
上面已經指出 letter-spacing 是支持負值的,那麼這個負值到底取多少合適呢?通過測試得出的結論是:inline-block 產生的空隙與父級元素繼承或者設定的 font-family、font-size 有關,一般狀況下,12px 大小的 tahoma 字體,inline-block 後元素間產生的空隙(間隙)大約是 5px;各個字體詳細狀況請參閱《inline-block空隙--letter-spacing與字體大小/字體關係數據表》。
第三步:修復 IE六、7 中始終存在的 1px 空隙
既然 letter-spacing 已經無能爲力了,那就試試 word-spacing 吧,直接設置 word-spacing:-1px。這裏須要注意的是,letter-spacing 和 word-spacing 同時使用可能致使衝突,因此咱們須要在 IE六、7 中 hack 掉 letter-spacing。最終代碼以下:
font-size:0;/* 全部瀏覽器 */
letter-spacing:-5px;/* Safari 等不支持字體大小爲 0 的瀏覽器 */
*letter-spacing:normal;
word-spacing:-1px;/* IE六、7 */
第四步:子元素重置回正常值
上述全部操做都是在父元素設置的,那麼子元素都會繼承這些屬性,字體大小爲0了,子元素就什麼都看不到了,這並非咱們想要的。 同時字符和單詞間距咱們也要把它重置爲默認值。「font-size: 12px; letter-spacing: normal; word-spacing: normal;」
最後:inline-block 更好的複用
或許你會擔憂每次我都要去看字體和空隙之間大小的關係嗎?其實否則,一般狀況下,全局字體都已經在 body 中指定了,根據全局字體設置合適的 letter-spacing 負值便可。如此一來,咱們即可以放心大膽的使用 inline-block 了,結合 OOCSS 的思想,能夠抽離出兩個複用的類,在須要設置 inline-block 元素的父級元素上定義一個「.dib-wrap」,該元素自身定義爲「.dib」。這裏還有一個問題須要注意的是:因爲 inline-block 具備 inline 元素的特性,在垂直方向上不少時候咱們並不但願元素以「vertical-align:baseline」方式來呈現,因此在「.dib-wrap」中統一重置爲「vertical-align:top」便可。
.dib-wrap {
font-size:0;/* 全部瀏覽器 */
*word-spacing:-1px;/* IE六、7 */
}
.dib-wrap .dib{
font-size: 12px;
letter-spacing: normal;
word-spacing: normal;
vertical-align:top;
}
@media screen and (-webkit-min-device-pixel-ratio:0){
/* firefox 中 letter-spacing 會致使脫離普通流的元素水平位移 */
.dib-wrap{
letter-spacing:-5px;/* Safari 等不支持字體大小爲 0 的瀏覽器, N 根據父級字體調節*/
}
}
.dib {
display: inline-block;
*display:inline;
*zoom:1;
}
其實在 YUI 3 中也全面運用了 inline-block 做爲基礎佈局,YUI 3 是這樣解決的:
.yui3-g {
letter-spacing: -0.31em; /* webkit: collapse white-space between units */
*letter-spacing: normal; /* reset IE < 8 */
word-spacing: -0.43em; /* IE < 8 && gecko: collapse white-space between units */
}.yui3-u {
display: inline-block;
zoom: 1; *display: inline; /* IE < 8: fake inline-block */
letter-spacing: normal;
word-spacing: normal;
vertical-align: top;
}
顯然,這裏純粹使用了 letter-spacing 和 word-spacing 來控制元素間的空隙,侷限性極大,-0.31em 和 -0.43em 只是由於 YUI 3 全局 cssfonts.css 裏設置是:「body { font:13px/1.231 arial,helvetica,clean,sans-serif; }」。
固然,若是你堅持使用把 html 寫在一行的方式來達到去除 inline-block 空隙的目的,我只能說:一切以犧牲結構來兼容表現的行爲都是耍流氓!因此探討此種方式去除空隙也將是無心義的,不在本文和做者考慮範圍以內。
IE5.5 後開始支持 inline-block, 比 CSS2.1 更早提出 inline-block 的概念並做爲所謂的「私有屬性值」使用。可是它所支持的 inline-block 不能等同於 CSS2.1 中的 inline-block,IE 5.五、六、7 、8(Q)中 block 元素對 inline-block 支持不完整,所以兩者表現出來的效果是不徹底一致。
產生 inline-block 空隙的根本性緣由是:HTML 中的換行符、空格符、製表符等合併爲空白符,字體大小不爲 0 的狀況下,空白符天然佔據必定的寬度,所以產生了元素間的空隙。
慎用 -webkit-text-size-adjust:none,它將會致使頁面沒法經過縮放來改變字體大小。
現在,Mac 平臺下的 Safari 6 已經支持 font-size:0 了,相信很快 Windows 平臺的 Safari 若是發佈 5.X 的更新,也會支持字體爲 font-size:0 了。等到 IE六、7 滅亡以後,世界就真真兒的美妙了!最後說一點:inline-block 與 float 也是沒法直接比較的,請不要再討論 inline-block 和 float 哪一個更好的話題了。inline-block 從 IE5.5 一路走來,存在便是合理,之後有時間在總結一下 inline-block 與 float 的使用場景的區別。
在不改變 CSS 定位機制的前提下,inline-block 應該是首選,而不是以「奇淫技巧」存在的。有感打油詩一首:
網事如煙
CSS 紅塵裏
inline-block 知多少
你在這頭
inline-block 在那頭
用與不用
它就在那裏
不悲不喜
PS:
爲了更好的排版,本文使用繁體中文引號 「」代替簡體中文小蝌蚪引號;
中英文混排的時候英文首尾各加一個空格;
之後文章有須要的時候也都將使用 gif 動畫配合說明。
操做系統版本: | Windows 7 企業版 6.1(內部版本 7600) |
---|---|
瀏覽器版本: | IE6 IE9 Firefox 14.0.1 Chrome 19.0.1084.46 Safari 5.1.7(7534.57.2) Opera 12.50 |