普通流(Normal Flow)javascript
在普通流中,元素按照其在 HTML 中的前後位置至上而下佈局,在這個過程當中,行內元素水平排列,直到當行被佔滿而後換行,塊級元素則會被渲染爲完整的一個新行, 除非另外指定,不然全部元素默認都是普通流定位,也能夠說,普通流中元素的位置由該元素在 HTML 文檔中的位置決定。
浮動 (Floats)css
在浮動佈局中,元素首先按照普通流的位置出現,而後根據浮動的方向儘量的向左邊或右邊偏移,其效果與印刷排版中的文本環繞類似。
絕對定位 (Absolute Positioning)html
在絕對定位佈局中,元素會總體脫離普通流,所以絕對定位元素不會對其兄弟元素形成影響(若是看了上文的童鞋,會發現這點與浮動元素會影響兄弟元素是不一樣的),而元素具體的位置由絕對定位的座標決定。
BFC 正是屬於普通流的,所以它對兄弟元素也不會形成什麼影響。java
塊格式化上下文(block formatting context) 是頁面 CSS 視覺渲染的一部分。它是用於決定塊盒子的佈局及浮動相互影響的一個區域。 --MDN 塊格式上下文segmentfault
個人理解是,BFC是一個環境,在這個環境中的元素不會影響到其餘環境中的佈局,也就是說,處於不一樣BFC中的元素是不會互相干擾的。瀏覽器
根元素或其它包含它的元素ide
浮動元素,float除none之外的值佈局
絕對定位元素 (元素的 position 爲 absolute 或 fixed)學習
display爲如下其中之一的值:inline-block,table-cell,table-captionflex
overflow 的值不爲 visible的元素
彈性盒子 flex boxes (元素的 display: flex 或 inline-flex)
其中,最多見的就是overflow:hidden、float:left/right、position:absolute。也就是說,每次看到這些屬性的時候,就表明了該元素以及建立了一個BFC了。
內部的盒會在垂直方向一個接一個排列(能夠看做BFC中有一個的常規流);
處於同一個BFC中的元素相互影響,可能會發生margin collapse;
每一個元素的margin box的左邊,與容器塊border box的左邊相接觸(對於從左往右的格式化,不然相反)。即便存在浮動也是如此;
BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素,反之亦然;
計算BFC的高度時,考慮BFC所包含的全部元素,連浮動元素也參與計算;
浮動盒區域不疊加到BFC上;
阻止外邊距摺疊
兩個相連的塊級元素在垂直上的外邊距會發生疊加,有些把這種狀況看做是bug,但我以爲多是出於段落排版的考慮,爲了令行間距一致纔有的這一特性。咱們先來看看例子:
<p>first</p> <p>second</p>
*{margin: 0px;padding: 0px} p { color: red; background: #eee; width: 100px; height: 100px; line-height: 100px; text-align: center; margin: 10px; border: solid 1px red; }
從上面能夠看出,咱們給兩個p元素都設置margin
,但中間的間距卻發生了摺疊。而後舉個BFC的例子:
.ele{ overflow: hidden; border: solid 1px red; }
<div class="ele"> <p>first</p> </div> <div class="ele"> <p>second</p> </div>
從上面能夠看出,咱們爲每一個div元素設置overflow
的值爲hidden
,產生一個塊級格式上下文,由於外邊距不會相互重疊。
BFC能夠包含浮動的元素
//html <div class = "box"> <div class= "floatL">float</div> <div class= "floatL">float</div> </div> <br style="clear:both"> <div class = "box BFC"> <div class= "floatL">float</div> <div class= "floatL">float</div> </div>
*{margin: 0px;padding: 0px} .floatL{ float: left; width: 100px; height: 100px; background-color: red; text-align: center; line-height: 100px; } .box{ border: 1px solid red; width: 300px; margin: 100px; padding: 20px; } .BFC{ overflow: hidden; *zoom: 1; }
從運行結果能夠看出,若是塊級元素裏面包含着浮動元素會發生高度塌陷,可是將它變成一個BFC後,BFC在計算高度時會自動將浮動元素計算在內。
BFC能夠阻止元素被浮動元素覆蓋
<div class="box1">box1</div> <div class="box2">box2</div>
*{margin: 0px; padding: 0px} .box1{ width: 100px; height: 100px; line-height: 100px; text-align: center; background-color: rgba(0, 0, 255, 0.5); border: 1px solid #000; float: left; } .box2{ width: 200px; height: 200px; line-height: 100px; text-align: center; background-color: rgba(255, 0, 0, 0.5); border: 1px solid #000; /* overflow: hidden; */ /* *zoom: 1; */ }
從上面看出,當元素浮動後,會與後面的塊級元素產生相互覆蓋。那怎麼解決這個問題,只要爲後面的元素建立一個BFC。添加overflow
屬性到box2
上。
overflow: hidden; *zoom: 1;
這樣子阻止了浮動元素重疊的問題。
hasLayout
除了使用 overflow: hidden
觸發 BFC 外,還使用了一個 *zomm: 1
的屬性,這是 IEhack ,由於 IE6-7 並不支持 W3C 的 BFC ,而是使用私有屬性 hasLayout
。從表現上來講,hasLayout
跟 BFC 很類似,只是 hasLayout
自身存在不少問題,致使了 IE6-7 中一系列的 bug 。觸發 hasLayout 的條件與觸發 BFC 有些類似,推薦爲元素設置 IE 特有的 CSS 屬性 zoom: 1
觸發 hasLayout
,zoom
用於設置或檢索元素的縮放比例,值爲「1」即便用元素的實際尺寸,使用 zoom: 1
既能夠觸發 hasLayout 又不會對元素形成其餘影響,相對來講會更爲方便。
拓展閱讀:
Block formatting context(塊級格式化上下文)
經典的清除浮動:
//利用僞元素清除浮動 .clearfix:after { content:"."; display:block; height:0; visibility:hidden; clear:both; } .clearfix { *zoom:1; }
拓展閱讀:
那些年一塊兒清除過的浮動
各類各樣的佈局,無非就是用了浮動 float,負邊距,相對定位,經過這三者的巧妙組合跟拼湊來實現的。用好這些,佈局就會很簡單。
還沒學會佈局時,就聽到有聖盃佈局和雙飛翼佈局,這佈局都有這麼風騷的名字,就以爲很酷,事實也如此,瞭解了聖盃佈局和雙飛翼佈局,才發現挺深奧的。
傳統的佈局中,當咱們須要改變兩欄的互換,就會很麻煩。由於還要涉及到 HTML 代碼的修改,不能徹底從 CSS 上更改,這叫 HTML 和 CSS 的耦合。而聖盃佈局跟雙飛翼佈局就是可以不考慮主體的位置,可以只經過 CSS 代碼就改變相應的佈局,這也是優勢之一。
試試這樣的HTML結構:
<div class="header">header</div> <div class="container"> <div class="main">main</div> <div class="sub">sub</div> <div class="extra">extra</div> </div> <div class="footer">footer</div>
給它加上CSS樣式:
body{ margin: 0; padding: 0; font-size: 1.5em; font-weight: bold; min-width: 500px;} .header,.footer{ text-align: center;} .header{ height: 50px; background-color: #76ffff;} .footer{ height: 50px; background-color: #ff7676;} .main{ background-color: #666;} .sub{ background-color: #44fa44;} .extra{ background-color: #3dbdff;} /*start*/ .main{ width: 100%; float: left; } .sub{ width: 100px; float: left; margin-left: -100%; } .extra{ width: 200px; float: left; margin-left: -200px; } .container{ overflow: hidden; }
結果以下:
會發現,main的位置不正確,因此再給container
加上 padding: 0 200px 0 100px
;
雖然 main 的位置正確了,但是 sub 和 extra 位置優勢不對,因此咱們再用上相對定位,爲 sub
和 extra
加上以下代碼:
.sub{ position: relative;; left: -100px; } .extra{ position: relative; right: -200px; }
效果就出來了,
噢耶,這就是聖盃佈局。若是在聖盃佈局的基礎上,給它一個多餘的標籤,把 mian 包起來,這就是雙飛翼佈局。
HTML結構:
<div class="header">header</div> <div class="container"> <div class="main"> <div class="main-wrap">main</div> </div> <div class="sub">sub</div> <div class="extra">extra</div> </div> <div class="footer">footer</div>
CSS結構:
body{ margin: 0; padding: 0; font-size: 1.5em; font-weight: bold; min-width: 500px;} .header,.footer{ text-align: center;} .header{ height: 50px; background-color: #76ffff;} .footer{ height: 50px; background-color: #ff7676;} .main{ background-color: #666;} .sub{ background-color: #44fa44;} .extra{ background-color: #3dbdff;} /*start*/ .main{ width: 100%; height: 100px; float: left; } .sub{ width: 100px; height: 100px; float: left; margin-left: -100%; } .extra{ width: 200px; height: 100px; float: left; margin-left: -200px; } .main-wrap{ margin: 0 200px 0 100px; } .container{ height: 100px; overflow: hidden; *zoom: 1; }
能夠看到,只要爲包住 main-wrap 設置 margin,連相對定位都沒用到,效果就出來了。
若是把三欄佈局比做一隻大鳥,能夠把main當作是鳥的身體,sub和extra則是鳥的翅膀。這個佈局的實現思路是,先把最重要的身體部分放好,而後再將翅膀移動到適當的地方。所以請允許我給這個佈局實現取名爲雙飛翼佈局(Flying Swing Layout).
就如上圖中的鳥有各類姿式同樣,利用雙飛翼佈局,咱們也能夠實現各類佈局。這裏有個嘗試頁面,利用雙飛翼,實現了一套柵格化佈局系統。
優勢:
實現了內容與佈局的分離,這是漸進式加強佈局的思想,從內容出發,不考慮佈局。
main部分是自適應寬度的,很容易在定寬佈局和流體佈局中切換。
任何一欄均可以是最高欄,不會出問題。
須要的hack很是少(就一個針對ie6的清除浮動hack:_zoom: 1;)
在瀏覽器上的兼容性很是好,IE5.5以上都支持。
缺點:
main須要一個額外的包裹層。
normalize 的理念則是儘可能保留瀏覽器的默認樣式,不進行太多的重置。
reset 的目的,是將全部的瀏覽器的自帶樣式重置掉,這樣更易於保持各瀏覽器渲染的一致性。
/* reset */ html,body,h1,h2,h3,h4,h5,h6,div,dl,dt,dd,ul,ol,li,p,blockquote,pre,hr,figure,table,caption,th,td,form,fieldset,legend,input,button,textarea,menu{margin:0;padding:0;} header,footer,section,article,aside,nav,hgroup,address,figure,figcaption,menu,details{display:block;} table{border-collapse:collapse;border-spacing:0;} caption,th{text-align:left;font-weight:normal;} html,body,fieldset,img,iframe,abbr{border:0;} i,cite,em,var,address,dfn{font-style:normal;} [hidefocus],summary{outline:0;} li{list-style:none;} h1,h2,h3,h4,h5,h6,small{font-size:100%;} sup,sub{font-size:83%;} pre,code,kbd,samp{font-family:inherit;} q:before,q:after{content:none;} textarea{overflow:auto;resize:none;} label,summary{cursor:default;} a,button{cursor:pointer;} h1,h2,h3,h4,h5,h6,em,strong,b{font-weight:bold;} del,ins,u,s,a,a:hover{text-decoration:none;} body,textarea,input,button,select,keygen,legend{font:12px/1.14 arial,\5b8b\4f53;color:#333;outline:0;} body{background:#fff;} a,a:hover{color:#333;}
以上reset來自NEC的css reset。
拓展閱讀:
Normalize.css 和 Reset CSS 有什麼本質區別?
IE條件註釋是一種特殊的HTML註釋,這種註釋只有IE5.0及以上版本才能理解。好比普通的HTML註釋是:
<!--This is a comment--> 而只有IE可讀的IE條件註釋是: <!--[if IE]> <![endif]--> 「非IE條件註釋」: <!--[if !IE]>--> non-IE HTML Code <!--<![endif]--> 「非特定版本IE條件註釋」(不多用到): <!--[if ! lt IE 7]> <![IGNORE[--><![IGNORE[]]> Code for browsers that match the if condition <!--<![endif]-->
簡而言之,除了「Windows上的IE」以外的全部瀏覽器都會認爲條件註釋只是一段普通的HTML註釋。你不能在CSS代碼中使用條件註釋。IE條件註釋是頗有用的對IE隱藏或者展示特定代碼的方法,比起在CSS中用詭異的_/製造bug,利用IE條件註釋來寫CSS 「hacks」是更合理的方法。通俗點,條件註釋就是一些if判斷,但這些判斷不是在腳本里執行的,而是直接在html代碼裏執行的。
條件註釋的基本結構和HTML的註釋(<!– –>)是同樣的。所以IE之外的瀏覽器將會把它們看做是普通的註釋而徹底忽略它們。
IE將會根據if條件來判斷是否如解析普通的頁面內容同樣解析條件註釋裏的內容。
條件註釋使用的是HTML的註釋結構,所以他們只能使用在HTML文件裏,而不能在CSS文件中使用。
從語法上看這是至關合法的普通HTML註釋。任何瀏覽器都會認爲<!–和–>之間的部分是註釋從而忽略它。可是IE也會看到其中[if IE]>,從而開始解釋接下來的代碼直到遇到<![endif]。因此,下面這些代碼不會顯示在任何其餘瀏覽器中面。
經過「比較操做符」能夠更靈活地對IE版本進行控制,用法是在IE前面加上「比較操做符」。合法的操做符以下:
lte:就是Less than or equal to的簡寫,也就是小於或等於的意思。
lt :就是Less than的簡寫,也就是小於的意思。
gte:就是Greater than or equal to的簡寫,也就是大於或等於的意思。
gt :就是Greater than的簡寫,也就是大於的意思。
! :就是不等於的意思,跟javascript裏的不等於判斷符相同
<!–[if gt IE 5.5]> / 若是IE版本大於5.5 / <!–[if lte IE 6]> / 若是IE版本小於等於6 / <!–[if !IE]> / 若是瀏覽器不是IE /
經常使用的IE條件註釋
<!--[if !IE]>除IE外均可識別<![endif]--> <!--[if IE]> 全部的IE可識別 <![endif]--> <!--[if IE 5.0]> 只有IE5.0能夠識別 <![endif]--> <!--[if IE 5]> 僅IE5.0與IE5.5能夠識別 <![endif]--> <!--[if gt IE 5.0]> IE5.0以及IE5.0以上版本均可以識別 <![endif]--> <!--[if IE 6]> 僅IE6可識別 <![endif]--> <!--[if lt IE 6]> IE6以及IE6如下版本可識別 <![endif]--> <!--[if gte IE 6]> IE6以及IE6以上版本可識別 <![endif]--> <!--[if IE 7]> 僅IE7可識別 <![endif]--> <!--[if lt IE 7]> IE7以及IE7如下版本可識別 <![endif]--> <!--[if gte IE 7]> IE7以及IE7以上版本可識別 <![endif]-->
要實現行內元素的水平居中,只需把行內元素包裹在塊級父層元(<div>、<li>、<p>
等)中,而且在父層元素CSS設置以下:
.container{ text-align: center; }
要實現塊狀元素(display:block)的水平居中,咱們只須要將它的左右外邊距margin-left和margin-right設置爲auto,便可實現塊狀元素的居中,要水平居中的塊狀元素CSS設置以下:
.container{ margin: 0 auto; }
利用絕對定位,將元素的top和left屬性都設爲50%,再利用margin邊距,將元素回拉它自己高寬的一半,實現垂直居中。核心CSS代碼以下:
.container{ position: relative; } .center{ position: absolute; left: 50%; top: 50%; margin: -50px 0 0 -50px; }
.container{ position: relative; } .center{ position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto; }
inline
或者inline-block
元素能夠巧妙的將父級容器設置爲display:table-cell
,配合text-align:center
和vertical-align:middle
便可以實現水平垂直居中。
.container{ width: 600px; height: 600px; background: #eee; display: table-cell; text-align: center; vertical-align: middle; } .center{ background: blue; }
利用C3的transform,能夠輕鬆的在未知元素的高寬的狀況下實現元素的垂直居中。
.container{ width: 100%; height: 400px; background: #eee; position: relative; } .center{ background: blue; position:absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
使用flex佈局,無需絕對定位等改變佈局的操做,能夠輕鬆實現元素的水平垂直居中。
.container{ width: 100%; height: 400px; background: #eee; /* flex 佈局解決水平居中 */ display: flex; justify-content: center; align-items: center; } .center{ width: 100px; height: 100px; background: blue; text-align: center; }
notes:CSS3的transform和flex有兼容性問題。ie11+才支持flexbox佈局。