一個設置容器和網格佈局的小技巧

查看bootstrap實現網格佈局的源碼,能夠發現: 網格容器(類屬性.container或者.container-fluid標識的元素),網格中的行(.row標識的元素)都包括了一個和類屬性.clearfix對應的CSS規則集。上述兩類CSS聲明中引用的mixin分別以下:html

.container-fixed(@gutter: @grid-gutter-width) {
    ...
    &:extend(.clearfix all);
}

.make-row(@gutter: @grid-gutter-width) {
    ...
  &:extend(.clearfix all);
}

.clearfix 是一個mixin,定義在一個單獨文件中,所有內容以下:前端

// Clearfix
//
// For modern browsers
// 1. The space content is one way to avoid an Opera bug when the
//    contenteditable attribute is included anywhere else in the document.
//    Otherwise it causes space to appear at the top and bottom of elements
//    that are clearfixed.
// 2. The use of `table` rather than `block` is only necessary if using
//    `:before` to contain the top-margins of child elements.
//
// Source: http://nicolasgallagher.com/micro-clearfix-hack/

.clearfix() {
  &:before,
  &:after {
    content: " "; // 1
    display: table; // 2
  }
  &:after {
    clear: both;
  }
}

註釋簡單解釋了兩條CSS屬性的設置理由,而且說明了這個clearfix的方法來自一個我的網站: http://nicolasgallagher.com/micro-clearfix-hack/bootstrap

這幾條CSS聲明至關簡短,可是對CSS沒有深刻理解的人恐怕一眼還看不明白(我就是看了半天還不明白的人),更不用說想出這麼一個絕妙的方法。app

這幾行聲明涉及到了好幾個CSS中關鍵的概念。在分析這幾行代碼的原理以前,首先要明白.clearfix的做用是什麼。當咱們建立一個佈局容器的時候,咱們但願這個容器內部的元素的佈局不受容器外部元素的影響,同時容器內部的元素也不要影響到外部的元素。clearfix就是爲了實現這個目的。框架

爲何這裏須要使用僞元素?

要屏蔽容器內部和外部元素的相互影響,確定要對容器內部的第一個元素和最後一個元素進行一些設置。若是一個前端佈局框架要求用戶必須對容器內的首尾兩個元素添加特定的class屬性來實現這個目的,那這個框架實在有點蠢。僞元素這個時候正好派上用場。
僞元素是僞的,由於它不屬於html/xml文檔,也不會被添加到DOM樹中,可是它在頁面上看起來又跟元素同樣,也能夠設置各類顯示屬性。ide

content: " "; display: table;

而後,咱們來看第一個規則集:content: " "; display: table;
爲何content要是" " (引號中間有個空格)。也就是說,content只有一個空格,而從標準 https://www.w3.org/TR/CSS2/visuren.html#block-formatting (9.4.2 Inline formatting contexts)中的規定看: 佈局

Line boxes that contain no text, no preserved white space, no inline elements with non-zero margins, padding, or borders, and no other in-flow content (such as images, inline blocks or inline tables), and do not end with a preserved newline must be treated as zero-height line boxes for the purposes of determining the positions of any elements inside of them, and must be treated as not existing for any other purpose. 網站

content中只有空格的時候,這個僞元素佔據的高度會是0,這正是咱們須要的。 ui

display爲何要設置爲table?

要回答這個問題,須要知道before這個僞元素在這裏發揮的是什麼做用。這裏before的做用避免margin-top的合併。
CSS中,垂直方向的相鄰margin是會合並的,這裏的所說的相鄰,不只包括兩個兄弟元素之間的相鄰margin,也包括一個容器內的首個元素和它的父元素之間的top margin,最後一個元素和父元素的bottom margin, 以及一個高度爲0的元素的上下margin。固然,margin也不是在任何狀況下都會合並,好比兩個相鄰margin之間有邊框的時候就不會合並。
若是不阻止這種合併,就會出現這種讓容器使用者以爲奇怪的現象:this


上面這個圖,粉紅色的區域是container, 淺藍色的區域是container內的第一個元素,這個元素以及container都設置了margin-top,並且都是20px,結果兩個margin合併了,給人的感受是第一個元素的margin-top根本沒生效。
如何阻止這種合併呢,那就要看合併何時會發生。標準文檔規定了多種兩個margin被認爲是相鄰的狀況(https://www.w3.org/TR/CSS2/box.html#collapsing-margins (8.3.1 Collapsing margins):

Two margins are adjoining if and only if:

  • 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 'auto' computed height
    • top and bottom margins of a box that does not establish a new block formatting context and that has zero computed 'min-height', zero or 'auto' computed 'height', and no in-flow children

當display設置爲table時,上面的第一條規則就不知足了,爲何呢?
這裏包含兩個緣由,首先是表格會產生一個匿名的table-cell, 而table-cell會建立一個新的block formatting context,因此before中的內容和container元素就再也不屬於同一個block formatting context。這兩點相關的CSS標準分別是:

https://www.w3.org/TR/CSS2/tables.html#anonymous-boxes

Any table element will automatically generate necessary anonymous table objects around itself, consisting of at least three nested objects corresponding to a 'table'/'inline-table' element, a 'table-row' element, and a 'table-cell' element.

https://www.w3.org/TR/CSS2/visuren.html#block-formatting

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

clear: both;

這一條規則的含義相對是比較明顯的,就是清除浮動。
當容器內的元素使用了float佈局的時候,若是不將僞元素after的兩側clear掉,float的元素就可能位於container外面,就像下面這樣:

 


由於float的元素並不會影響container的高度。
容器內的元素漂到了容器外面,這顯然不是咱們指望的行爲。clear 僞元素after兩側的結果就是,after必須放在float的元素的下面,container就被撐高了,就像下面這樣:

注:爲了更清楚的看到僞元素的做用,這裏把after的content設置爲了"after pseudo"。

結語

這簡短的幾行代碼居然涉及了這麼多CSS佈局的基礎性原理。

相關文章
相關標籤/搜索