【從0到1學Web前端】CSS定位問題一(盒模型,浮動,BFC) 分類: HTML+CSS 2015-05-27 22:24 813人閱讀 評論(1) 收藏

引子:

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

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

效果以下圖:
這裏寫圖片描述css3

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

第一種實現方法,是藉助css3的新屬性calc,實現代碼以下:chrome

body { margin: 0; padding: 0; font-size:0; }
.left_div { background-color: #62FF09; /*calc是css3屬性能夠動態計算,兼容不一樣瀏覽器的類型須要加識別的前綴,很是重要的是要有空格*/ width: -webkit-calc(50% - 50px); width: calc(50%-50px); height: 200px; }
.mid_div { width: 100px; height: 200px; margin-left: -50px; background-color: #20FFDA; margin:0 auto; }
.right_div { background-color: #FFF81B; height: 200px; width: -webkit-calc(50% - 50px); }
div{display:inline-block;}

第二種實現方式就是藉助與display屬性,將全部的div框具備table的單元格的屬性.
代碼以下:瀏覽器

* {
    padding: 0;
    margin: 0;
}
.left_div, .mid_div, .right_div {
    height: 200px;
    display: table-cell;
}
.left_div {
    width: 50%;
    background: #369;
}
.mid_div {
    //非IE識別的屬性,(>=IE8)
    min-width: 100px;
    width: 100px;
    background: #697;
}
.right_div {
    width: 50%;
    background: #126;
}

這裏解決問題的主要思路是當中間的寬度肯定後,由於全部div是單元格因此使用50%使左右的單元格平分剩下的寬度.markdown


1.盒模型

盒模型又分IE盒模型和非IE盒模型:
看下面的一張圖(來自維基百科):佈局

這裏寫圖片描述
由上面的圖能夠知道IE和非IE盒模型的區別主要是計算元素的寬度和高度不同。測試

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

看一段代碼:spa

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

效果以下:
這裏寫圖片描述

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

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

以下圖:
這裏寫圖片描述

這是爲何呢?

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

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

這裏寫圖片描述

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

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

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

我非別在非IE瀏覽器(且>=IE8也一樣的效果)中測試的結果以下:

這裏寫圖片描述

在IE7中的效果以下圖:
這裏寫圖片描述

在<=IE6之下顯示的效果以下(默認會將父級框撐開):

這裏寫圖片描述

關於div的最小(最大)寬度和高度在IE8(>=)之上和非IE瀏覽器上都實現了min-height,maxheight,min-width,max-width這四個屬性。

關於body的問題:

看下面一段代碼:

<style type="text/css"> *{margin:0;padding:0;} div{ width:300px; height:200px; background-color:#9feb3d; } body{ border:5px 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>

而且代碼的效果圖以下:

這裏寫圖片描述

由上能夠知道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:0;margin:0px;}
        span{ background-color:#f73bd6; margin:0 0 0 10px; }
        .test-float1{ float:left; height:100px; width:20px; }
        .test-float2{ /*float:left;*/ height:100px; width:20px; }

效果以下:

這裏寫圖片描述

由上面的代碼咱們能夠得出一個結論,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:0; } .item1, .item2, .item3, .item4{ width:200px; height:100px; background-color:#d8f73b; margin:10px 0 0 0; } .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,以下圖:

這裏寫圖片描述

能夠很明顯的看到在浮動的item1和item2有一個間隔沒有在一條水平線上。

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

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

效果以下圖:

這裏寫圖片描述

有關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:0;} #body-div{ background-color:#ffff99; border:1px solid #111111; padding:5px; } #body-div div{ padding:10px; margin:15px; background-color:#90baff; } #body-div p{ border:5px dashed #111111; background-color:#ff90ba; } .item1{ border:5px dashed #111111; /*float:left;*/ } .item2{ border:5px dashed #f73b4d; } .item3{ border:5px 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>

顯示效果以下圖:

這裏寫圖片描述

2.1爲Box-1設置浮動

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

效果以下圖:

這裏寫圖片描述

能夠看到標準流中的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:5px dashed #f73b4d; float:left; }

效果以下圖:

這裏寫圖片描述

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

2.3爲Box-3設置浮動

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

效果以下圖:

這裏寫圖片描述

這個時候能夠很明顯的看出三個浮動的盒子(都脫離文檔流)都被P標籤的盒子所包圍,而且被文字環繞。

2.4設置Box-3浮動的方向

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

效果以下圖:

這裏寫圖片描述

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

這裏寫圖片描述

注意:

這種效果我只在IE瀏覽器(<=IE8的瀏覽器中出現更怪異的狀況)裏面測試的時候能夠小到讓Box-3換行。

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

以下圖:

這裏寫圖片描述

這時若是咱們設置item2右浮動item3左浮動當我縮小瀏覽器窗口的時候,會出現以下的狀況(mac下chrome和safari中仍舊是之上的狀況,縮小到必定寬度沒法再縮小)。

這裏寫圖片描述

由此咱們能夠得出一個結論:

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

2.5浮動的邊界

增長Box-1的高度,當縮小瀏覽器的寬度的時候,會出現以下的現象:

這裏寫圖片描述

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

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

這裏寫圖片描述

2.6取消浮動的影響

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

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

代碼以下:

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

效果以下:
這裏寫圖片描述

2.7浮動的影響

固然浮動對父級元素也會帶來影響,好比說偉大的「塌陷」,看代碼:

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

效果以下圖:

這裏寫圖片描述

全部子元素的浮動不會將父級元素的高度撐開。

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

一個很古老的辦法就是在全部子元素的末尾添加一個空的div,而且設置它的clear:both。
看代碼以下:

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

效果以下:

這裏寫圖片描述

其實我在IE各版本瀏覽器和非IE瀏覽器中測試的效果都是如上面的效果可意很容易的發現父級的div盒子並無被徹底的撐開。

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

版本一:

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

    .clearfix { *zoom: 1;/*IE/7/6*/ }

content:」\200B」;這個參數,Unicode字符裏有一個「零寬度空格」,即 U+200B,代替原來的「.」,能夠縮減代碼量。並且再也不使用visibility:hidden。

版本二:

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

通過測試在IE的各個版本的瀏覽器中和非IE瀏覽器都可以正常的獲得結果。

這裏寫圖片描述

推薦閱讀:

清除浮動:

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

相關文章
相關標籤/搜索