天天看點

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

引子:

在談到css定位問題的時候先來看一個小問題:

已知寬度(假如:100px)div框,水準居中,左右兩百年的分别使用div框填充.且左右div自适應.

效果如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

這個問題的難點主要是浏覽器寬度未知,且兩邊div自适應寬度.

第一種實作方法,是借助css3的新屬性calc,實作代碼如下:

body {
    margin: ;
    padding: ;
    font-size:;
}
.left_div {
    background-color: #62FF09;
    /*calc是css3屬性可以動态計算,相容不同浏覽器的類型需要加識别的字首,非常重要的是要有空格*/
    width: -webkit-calc(% - px);
    width: calc(%-px);
    height: px;
}
.mid_div {
    width: px;
    height: px;
    margin-left: -px;
    background-color: #20FFDA;
    margin: auto;
}
.right_div {
    background-color: #FFF81B;
    height: px;
    width: -webkit-calc(% - px);
}
div{display:inline-block;}
           

第二種實作方式就是借助與display屬性,将所有的div框具有table的單元格的屬性.

代碼如下:

* {
    padding: ;
    margin: ;
}
.left_div, .mid_div, .right_div {
    height: px;
    display: table-cell;
}
.left_div {
    width: %;
    background: #369;
}
.mid_div {
    //非IE識别的屬性,(>=IE8)
    min-width: px;
    width: px;
    background: #697;
}
.right_div {
    width: %;
    background: #126;
}
           
這裡解決問題的主要思路是當中間的寬度确定後,因為所有div是單元格是以使用50%使左右的單元格平分剩下的寬度.

1.盒模型

盒模型又分IE盒模型和非IE盒模型:

看下面的一張圖(來自維基百科):

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

由上面的圖可以知道IE和非IE盒模型的差別主要是計算元素的寬度和高度不一樣。

  1. IE浏覽器: margin-left+width+margin-right
  2. 非IE浏覽器:margin-left+border-left+padding-left+width+padding-right+border-right+margin-right

看一段代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>box-html</title>
    <style type="text/css">
        *{margin:;padding:;}
        #body-box{
            width:px;
            height:px;
            background-color:#FF00FF;
            /*overflow:hidden;*/
        }
        .box-style{
            width:px;
            height:px;
            border:px dashed black;
            background-color:red;
            margin:px   px;
            padding: px px px px;
        }
    </style>
</head>
<body>
    <div id="body-box">
        <div class="box-style">你好帥呀</div>
    </div>
</body>
</html>
           

效果如下:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

很明顯我們發現一個問題,就是子元素的margin-top作用在了父元素上。

當我們給父元素添加一個overflow:hidden屬性時,結果正常。

如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

這是為什麼呢?

overflow 樣式值為 非 visilbe 時,實際上是建立了 CSS 2.1 規範定義的 Block Formatting Contexts。建立了它的元素,會重新計算其内部元素位置,進而獲得确切高度。這樣父容器也就包含了浮動元素高度。這個名詞過于晦澀,在 CSS 3 草案中被變更為名詞 Root Flow,顧名思義,是建立了一個新的根布局流,這個布局流是獨立的,不影響其外部元素的。實際上,這個特性與 早期 IE 的 hasLayout 特性十分相似。

經過測試在IE8以上的浏覽器表現與chrome和firefox浏覽器表現效果相同。但是在IE7以下浏覽器不用設定這個屬性就可以表現正常的效果。如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

下面的文字出現錯誤:

很明顯發現的一個問題就是IE8(包括IE8)以上浏覽器的background-color是border+padding+content*.而IE8(不包括)是*padding+content。

上面的結論是我在 IE11 浏覽器中模拟IE8和IE9得出的結論,上面的文字是有問題的(可能是因為更新IE11後,浏覽器的解析核心跟IE8和IE9不一樣,因為微軟IE浏覽器的标準也是一直在改變的)。

在真實的IE8和IE9中

background-color

都僅僅是padding+content 。而IE11中

background-color

border+padding+content

再來看一個示例,代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TestBox</title>
    <style type="text/css">
    body{margin:;}
    .item1{
        width:px;
        height:px;
        border:px solid #f73bd6;
        padding:px   ;
    }
    .item2{
        width:px;
        height:px;
        margin:px   ;
        border:px solid #f73bd6;
    }
    </style>
</head>
<body>
    <div class="item1">
        <div class="item2"></div>
    </div>
</body>
</html>
           

我非别在非IE浏覽器(且>=IE8也同樣的效果)中測試的結果如下:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

在IE7中的效果如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

在<=IE6之下顯示的效果如下(預設會将父級框撐開):

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)
關于div的最小(最大)寬度和高度在IE8(>=)之上和非IE浏覽器上都實作了min-height,maxheight,min-width,max-width這四個屬性。

關于body的問題:

看下面一段代碼:

<style type="text/css">
        *{margin:;padding:;}
        div{
            width:px;
            height:px;
            background-color:#9feb3d;
        }
        body{
            border:px solid #eb3dda;
            background-color:#3d3deb;
        }
    </style>
<body>
    <div>
        <ul>
            <li>你是第1個</li>
            <li>你是第2個</li>
            <li>你是第3個</li>
            <li>你是第4個</li>
            <li>你是第5個</li>
        </ul>
    </div>
</body>
           

并且代碼的效果圖如下:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)
由上可以知道body是一個特殊的div(盒子)。它的background-color會延伸到margin。

标準流的概念:

在不使用其他的與排列和定位相關的特殊CSS規則時,各種元素的排列規則。

2.浮動

float 屬性定義元素在哪個方向浮動。以往這個屬性總應用于圖像,使文本圍繞在圖像周圍,不過在 CSS 中,任何元素都可以浮動。浮動元素會生成一個塊級框,而不論它本身是何種元素,且浮動元素的寬度是根據内容的寬度确定的。

看下面的一段代碼:

<body>
    <span class="test-float1">你好吧</span>
    <span class="test-float2">我是還是吧</span>
</body>
           

然後分别對.test-float1和.test-float2應用樣式,代碼如下:

*{padding:;margin:px;}
        span{
            background-color:#f73bd6;
            margin:   px;
        }
        .test-float1{
            float:left;
            height:px;
            width:px;
        }
        .test-float2{
            /*float:left;*/
            height:px;
            width:px;
        }
           

效果如下:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

由上面的代碼我們可以得出一個結論,span作為一個行内元素本來是沒有width和height屬性的,但是當對行内元素使用float屬性後,該元素具有了width和height屬性。

注意:

假如在一行之上隻有極少的空間可供浮動元素,那麼這個元素會跳至下一行,這個過程會持續到某一行擁有足夠的空間為止。

浮動的框可以向左或向右移動,直到它的外邊緣碰到包含框或另一個浮動框的邊框為止。由于浮動框不在文檔的普通流中,是以文檔的普通流中的塊框表現得就像浮動框不存在一樣。

看下面的一段代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TestFloat</title>
    <style type="text/css">
        body{
            margin:;
        }

        .item1, .item2, .item3, .item4{
            width:px;
            height:px;
            background-color:#d8f73b;
            margin:px   ;
        }
        .item1{
            float:right;
        }
        .item2{
            /*float:left;*/
        }

    </style>
</head>
<body>
    <div id="body-div">
        <div class="item1">item1</div>
        <div class="item2">item2</div>
        <div class="item3">item3</div>
        <div class="item4">item4</div>
    </div>
</body>
</html>
           

這個時候看到頁面的結果有一個很明顯的bug,如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

可以很明顯的看到在浮動的item1和item2有一個間隔沒有在一條水準線上。

這個時候就回到了我們開頭的問題,我們給父級的div盒子添加overflow屬性觸發父級div的BFC。代碼如下:

<style type="text/css">
        body{
            margin:;
        }
        //觸發父級元素的BFC
        #body-div{
            overflow:hidden;
        }
        .item1, .item2, .item3, .item4{
            width:px;
            height:px;
            background-color:#d8f73b;
            margin:px   ;
        }
        .item1{
            float:right;
        }
        .item2{
            /*float:left;*/
        }

    </style>
           

效果如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

有關BFC的定義:

BFC(W3C CSS 2.1 規範中的一個概念)就是所謂的Block formatting contexts (塊級格式化上下文)。建立了 BFC的元素就是一個獨立的盒子,裡面的子元素不會在布局上影響外面的元素,反之亦然,同時BFC仍然屬于文檔中的普通流。

那麼怎麼觸發BFC呢?

  1. float 除了none以外的值
  2. overflow 除了visible 以外的值(hidden,auto,scroll )
  3. display (table-cell,table-caption,inline-block)
  4. position(absolute,fixed)
  5. fieldset元素

注意:

display:table 本身并不會建立BFC,但是它會産生匿名框(anonymous boxes),而匿名框中的display:table-cell可以建立新的BFC,換句話說,觸發塊級格式化上下文的是匿名框,而不是 display:table。是以通過display:table和display:table-cell建立的BFC效果是不一樣的。
fieldset 元素在www.w3.org裡目前沒有任何有關這個觸發行為的資訊,直到HTML5标準裡才出現。有些浏覽器bugs(Webkit,Mozilla)提到過這個觸發行為,但是沒有任何官方聲明。實際上,即使fieldset在大多數的浏覽器上都能建立新的塊級格式化上下文,開發者也不應該把這當做是理所當然的。CSS 2.1沒有定義哪種屬性适用于表單控件,也沒有定義如何使用CSS來給它們添加樣式。使用者代理可能會給這些屬性應用CSS屬性,建議開發者們把這種支援當做實驗性質的,更高版本的CSS可能會進一步規範這個。

BFC的特性:

1)塊級格式化上下文會阻止外邊距疊加

當兩個相鄰的塊框在同一個塊級格式化上下文中時,它們之間垂直方向的外邊距會發生疊加。換句話說,如果這兩個相鄰的塊框不屬于同一個塊級格式化上下文,那麼它們的外邊距就不會疊加。

2)塊級格式化上下文不會重疊浮動元素

根據規定,一個塊級格式化上下文的邊框不能和它裡面的元素的外邊距重疊。這就意味着浏覽器将會給塊級格式化上下文建立隐式的外邊距來阻止它和浮動元 素的外邊距疊加。由于這個原因,當給一個挨着浮動的塊級格式化上下文添加負的外邊距時将會不起作用(Webkit和IE6在這點上有一個問題——可以看這 個測試用例)。

3)塊級格式化上下文通常可以包含浮動

觸發了BFC的話,就不會被float元素覆寫,當子元素全部浮動的時候也能夠正确地包含了

深入研究浮動:

來看下面的一段代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
        body{margin:;}
        #body-div{
            background-color:#ffff99;
            border:px solid #111111;
            padding:px;
        }
        #body-div div{
            padding:px;
            margin:px;
            background-color:#90baff;
        }
        #body-div p{
            border:px dashed #111111;
            background-color:#ff90ba;
        }
        .item1{
            border:px dashed #111111;
            /*float:left;*/
        }
        .item2{
            border:px dashed #f73b4d;

        }
        .item3{
            border:px dashed #0000CD;

        }
    </style>
</head>
<body>
    <div id="body-div">
        <div class="item1">Box-1</div>
        <div class="item2">Box-2</div>
        <div class="item3">Box-3</div>
        <p>讓我們更詳細地看看浮動和清理。假設希望讓一個圖檔浮動到文本塊的左邊,并且希望這幅圖檔和文本包含在另一個具有背景顔色和邊框的元素中。您可能編寫下面的代碼:讓我們更詳細地看看浮動和清理。假設希望讓一個圖檔浮動到文本塊的左邊,并且希望這幅圖檔和文本包含在另一個具有背景顔色和邊框的元素中。您可能編寫下面的代碼:讓我們更詳細地看看浮動和清理。假設希望讓一個圖檔浮動到文本塊的左邊,并且希望這幅圖檔和文本包含在另一個具有背景顔色和邊框的元素中。您可能編寫下面的代碼:</p>
    </div>
</body>
</html>
           

顯示效果如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

2.1為Box-1設定浮動

.item1{
            border:px dashed #111111;
            float:left;
        }
           

效果如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

可以看到标準流中的Box-2的文字在圍繞着Box-1排列,而此時的Box-1的寬度不再伸展,而是能容納下内容的最小寬度。

因為此時的Box-1已經脫離了标準流,标準流中的Box-2會頂到原來Box-1的位置(也就是Box-2的左邊框和Box-1的左邊框重合)此時Box-2的文字會圍繞着Box-1排列。

2.2為Box-2設定浮動

.item2{
            border:px dashed #f73b4d;
            float:left;
        }
           

效果如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

這是很容易看出Box-3和Box-1的左邊框重合。Box-3的文字圍繞Box-2,并且Box-1和Box-2之間的空白是兩者之間的margin産生的。

2.3為Box-3設定浮動

.item3{
            border:px dashed #0000CD;
            float:left;

        }
           

效果如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

這個時候可以很明顯的看出三個浮動的盒子(都脫離文檔流)都被P标簽的盒子所包圍,并且被文字環繞。

2.4設定Box-3浮動的方向

.item3{
            border:px dashed #0000CD;
            float:right;

        }
           

效果如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

這個時候當我把浏覽器視窗的寬度逐漸的縮小到不能容納三個div寬度的時候,會有什麼效果呢?如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

注意:

這種效果我隻在IE浏覽器(<=IE8的浏覽器中出現更怪異的情況)裡面測試的時候可以小到讓Box-3換行。

在mac下得chrome,firefox和safari當視窗縮小到一定的寬度的時候,就無法在縮小寬度。無法出現Box-3被擠到下一行的情況。

如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

這時如果我們設定item2右浮動item3左浮動當我縮小浏覽器視窗的時候,會出現如下的情況(mac下chrome和safari中仍舊是之上的情況,縮小到一定寬度無法再縮小)。

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

由此我們可以得出一個結論:

當浮動的元素在一行無法顯示完全時,元素會按照普通流的順序(Dom排列順序)被擠到下一行。

2.5浮動的邊界

增加Box-1的高度,當縮小浏覽器的寬度的時候,會出現如下的現象:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

主要是因為這個時候Box-3的邊緣被Box-1的邊緣卡住的緣故。

如下圖紅色的地方會有三個margin值:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

2.6取消浮動的影響

使用CSS屬性Clear,它有三個值left,right,both。

如我們取消p元素左右兩側的浮動:

代碼如下:

#body-div p{
            border:px dashed #111111;
            background-color:#ff90ba;
            clear:both;
        }
           

效果如下:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

2.7浮動的影響

當然浮動對父級元素也會帶來影響,比如說偉大的“塌陷”,看代碼:

<style type="text/css">
        body{margin:;}
        #body-div{
            background-color:#ffff99;
            border:px solid #111111;
            padding:px;
        }
        #body-div div{
            padding:px;
            margin:px;
            background-color:#90baff;
        }
        #body-div p{
            border:px dashed #111111;
            background-color:#ff90ba;
            clear:both;
        }
        .item1{
            border:px dashed #111111;
            float:left;
            height:px;
        }
        .item2{
            border:px dashed #f73b4d;
            float:left;
        }
        .item3{
            border:px dashed #0000CD;
            float:left;

        }
    </style>
           

效果如下圖:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)
所有子元素的浮動不會将父級元素的高度撐開。

那麼怎麼解決這個問題呢?

一個很古老的辦法就是在所有子元素的末尾添加一個空的div,并且設定它的clear:both。

看代碼如下:

#body-div  .clear-float{
            clear:both;
            border:;
            padding:;
            margin:;
        }
           

效果如下:

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

其實我在IE各版本浏覽器和非IE浏覽器中測試的效果都是如上面的效果可意很容易的發現父級的div盒子并沒有被完全的撐開。

不過有大神已經研究出了clearfix的寫法,可以達到最合理的效果,主要目的就是觸發父級盒子自身的BFC。

版本一:

.clearfix:after {
        content: "\200B";
        display: block;
        height: ;
        clear: both;
    }

    .clearfix {
        *zoom: ;/*IE/7/6*/
    }
           
content:”\200B”;這個參數,Unicode字元裡有一個“零寬度空格”,即 U+200B,代替原來的“.”,可以縮減代碼量。而且不再使用visibility:hidden。

版本二:

.clearfix:before, .clearfix:after {
    content: "";
    display: table;
}
.clearfix:after {
    clear: both;
}
.clearfix {
*zoom: ;        /*IE/7/6 */
}
           

經過測試在IE的各個版本的浏覽器中和非IE浏覽器都能夠正常的得到結果。

【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC)

推薦閱讀:

清除浮動:

http://mp.weixin.qq.com/s?__biz=MjM5MzMyNzg0MA==&mid=205433384&idx=2&sn=dbee05fdab1039a1bfa8d5e3dbbec76b&scene=5#rd

深入了解BFC:

http://www.cnblogs.com/v10258/p/3530290.html