1. 程式人生 > >拜拜了,浮動佈局-基於display:inline-block的列表佈局 張鑫旭部落格筆記

拜拜了,浮動佈局-基於display:inline-block的列表佈局 張鑫旭部落格筆記

by zhangxinxu from http://www.zhangxinxu.com

一、列表浮動佈局的侷限

所以,如果我們要使用浮動佈局列表,就必須限高,於是,不得已,需要裁掉超多的使用者名稱資訊。

浮動本身就是個魔鬼,所以,使用浮動佈局還需要修復其帶來的副作用——高度塌陷的問題,也就是常提到的“清除浮動”了。

另外,IE6下,重複的列表元素會出現莫名的bug,例如出現不知哪來的文字。

由於浮動佈局學習與理解的門檻低,又受主流之風驅動,且滿足了絕大多數的佈局需求。所以,在追尋更好的佈局方式上,大家的願望似乎不是很強烈,當然,可能是自己井底之蛙了,不過從國內領先網站的列表佈局情況來看,貌似浮動佈局還是紮根很深的(這回在列表佈局上,人人網讓我刮目了一把)。

二、另外一種display屬性,display:inline-block

(

inline-block 和 block區別

block和inline這兩個概念是簡略的說法,完整確切的說應該是 block-level elements (塊級元素) 和 inline elements (內聯元素)。block元素通常被現實為獨立的一塊,會單獨換一行;inline元素則前後不會產生換行,一系列inline元素都在一行內顯示,直到該行排滿。

一般來說,可以通過display:inline和display:block的設定,改變元素的佈局級別。

  • display:block
    1. block元素會獨佔一行,多個block元素會各自新起一行。預設情況下
      ,block元素寬度自動填滿其父元素寬度。
    2. block元素可以設定width,height屬性。塊級元素即使設定了寬度,仍然是獨佔一行。
    3. block元素可以設定margin和padding屬性。
  • display:inline
    1. inline元素不會獨佔一行,多個相鄰的行內元素會排列在同一行裡,直到一行排列不下,才會新換一行,其寬度隨元素的內容而變化。
    2. inline元素設定width,height屬性無效。
    3. inline元素的margin和padding屬性,水平方向的padding-left, padding-right, margin-left, margin-right都產生邊距效果;但豎直方向的padding-top, padding-bottom, margin-top, margin-bottom不會產生邊距效果。
  • display:inline-block  直觀理解:行內的block
    1. 簡單來說就是將物件呈現為inline物件,但是物件的內容作為block物件呈現。之後的內聯物件會被排列在同一行內。比如我們可以給一個link(a元素)inline-block屬性值,使其既具有block的寬度高度特性又具有inline的同行特性。
    2. 在內部他的表現類似block元素,比如他擁有block元素的width height,padding,border與margin,而外部的排列方式有類似行內元素,即水平排列(比如一個inline-block後面的inline元素會水平排列在它的後面),而不是像塊級元素一樣從上到下排列
)

display:inline-block感覺與display:table-cell有些相似,例如對內部元素的包裹性。但是,由於display:inline-block最大的不同就是其沒有父元素的匿名包裹特性,這使得display:inline-block屬性的使用非常自由,可與文字,圖片混排,可內嵌block屬性元素,可以可以置身於inline水平的元素中。可謂黑白通吃,左右逢源。

inline-block屬性的元素適用於inline box模型,所以,當其中的列表元素高度不一時,是不會有錯位的。關於line box模型,我在之前的“css行高line-height的一些深入理解及應用”第二部分提到了,以及前面“CSS float浮動的深入研究、詳解及拓展(一)”一文的“浮動的破壞性”部分中做過比較詳細的介紹。一言以蔽之,就是每一行所有的inline元素和inline-block元素會共同形成一個line boxes,這個line box的高度由裡面最高的元素決定。所以,即使inline-block屬性的列表元素高度異常,撐開的是整個line boxes的高度,因而,不會與下一行的列表元素髮生錯位。如下面的我自己畫得拙劣的示意圖所示的:
line boxes讓inline-block元素不會犬牙交錯排列 張鑫旭-鑫空間-鑫生活

根據一些前輩的說法,IE6/7不支援display:inline-block屬性,只是可以讓標籤有類似於inline-block的屬性,起初我也是接受這種說法的,不過後來又表示了懷疑,最近使用text-align:justify;做測試的時候的一些樣式表現證實了:確實IE6/7是不支援display:inline-block屬性,只是讓其表現的跟inline-block一樣,尤其對於inline水平的元素,其表現度可以用perfect一詞來形容了。

對於IE8+以及現代瀏覽器,直接使用:

{display:inline-block;}

就可以了,支援任意水平的元素。

對於不支援的IE6/7瀏覽器該怎麼辦呢?如果是inline水平的元素(如a標籤,span標籤之類)跟上面一樣,直接:

{display:inline-block;}

就可以了,對於這兩個瀏覽器,其功效與*zoom:1;是一樣的。

如果是block水平的元素,例如li標籤。則需要多點程式碼,目前我知道的方法有兩個,如下所示:

li {display:inline-block;...}
li {display:inline;}

或者是:

li{display:inline; zoom:1;...}

block水平的inline-block化的元素與inline水平的在表現層又是有差異的,這個後面會談到。

但是,這種做法好傻啊,而且HTML程式碼的可讀性很不好。尤其考慮到現實情況:後臺人員可能不清楚標籤換行對樣式的影響,直接後臺repeat的時候,換行了。所以,此方法頂多臨時應付些小打小鬧的地方,要想廣泛使用,顯然業餘了。

其實,我們只要細細想想,空格符本質上就是個字元,與a,b,c,d這些字元是個同一個屬性的東西,只是他是空格,透明的看不見而已(但可以選中)。所以,只要我們使用讓文字寬度為0的那些方法,不就可以解決inline-block元素間換行符間隙的問題啦!

於是,很自然而然的,想到了以下樣式:

{font-size:0;}

我還記得我大學時候解決IE6下標籤高度無法小於11畫素bug時的方法,就是使用的font-size:0;這屬性可以讓莫名的空格啊神馬東東的都變成浮雲。我們來試下,可否用來消除inline-block元素間的換行間隙的問題。
如下測試程式碼:


ok,現在我們把上面嘮嘮叨叨的些東西提煉整理一下,有如下一些結論:
» block水平的元素inline-block化後,IE6/7沒有換行符間隙問題,其他瀏覽器均有;
» inline水平的元素inline-block後,所有主流瀏覽器都有換行符/空格間隙問題;
» font-size:0,去除換行符間隙,在IE6/7下殘留1畫素間隙,Chrome瀏覽器無效,其他瀏覽器都完美去除;
» letter-spacing負值可以去除所有瀏覽器的換行符間隙,但是,Opera瀏覽器下極限是間隙1畫素,0畫素會反彈,換行符間隙還原。

為什麼袁隆平的水稻牛逼啊,就是因為是雜交的。這也是不宜近親結婚之道,雜交可以產生彪悍的下一代。這個原理同樣適用於CSS,雖然font-size:0有缺陷,letter-spacing負值也有不足,但是一旦將它們強制交配,哦呵呵,互補與整合,換行符間隙問題迎刃而解。如下測試程式碼(環境字型大小84%,字型Arial):