前言
首先聲明在這篇博客里我將不會細說每一個知識點(比如什么是BFC,什么是flex等等),我主要是總結一下自己對標題中所列三個知識點的一些方法。
一、多欄自適應布局
首先,在這里我將從最簡單的兩欄固定布局慢慢講到多欄自適應布局。
1.固定布局
說到固定布局想必大家已經覺得無愛了,但我還是要簡單地講一下,下面通過一個簡單的實例進行講解:
html代碼:
<div class="wrap"> <div class="left">left</div> <div class="right">right</div> </div>
css代碼:
.wrap{ width:500px; height:400px; border:1px solid red; margin:0 auto; } .left{ width:200px; height:400px; background:#ccc; } .right{ width:300px; height:400px; background:#ddd; }
我們希望的布局效果是500px寬的容器內分別有一個200px寬和300px寬的子元素容器,可此時運行結果為:
這是因為div元素是塊級元素,默認是會占據整行的,於是我們就采用浮動的方法來解決這個問題。
此時我們只需要再添加如下樣式:
.left,.right{ float:left; }
那么就能得到我們想要的結果了:
由於這里只有兩欄布局,而且都是固定布局,並且剛好占滿父容器,所以第二個子元素右浮動也是一樣的效果。但如果是多欄布局(比如四欄布局)並且剛好占滿父容器的話,那么最后一個可以是左浮動或者右浮動。
對於兩欄固定布局,其實並不一定兩個子元素都需要左浮動,可以第一個子元素左浮動,第二個設置margin-left值撐開就行了:
.left{ float:left; } .right{ margin-left:200px; }
這樣也能實現上面的效果。但如果是多欄固定布局,個人覺得還是浮動比較方便。
在固定布局中,除了浮動之外,還有一種比較常用的方法就是定位。
把上面的樣式代碼改一改:
.wrap{ position:relative; } .left{ position:absolute; top:0; left:0; } .right{ position:absolute; top:0; left:200px; }
這樣寫同樣能達到之前的那種效果,但定位布局比較煩的就是得精確計算每一塊的位置。
所以,個人覺得目前固定布局一般會結合浮動+定位+必要時的內外邊距來進行布局會更加實用。當然了,浮動+定位+內外邊距也同樣適用於自適應布局,彼此之間都不是等號關系的。
2.兩欄自適應布局
同樣是上面的實例,我把它改成自適應布局:
.wrap{ width:80%; height:400px; border:1px solid red; margin:0 auto; } .left{ width:40%; height:100%; float:left; background:#ccc; } .right{ width:60%; height:100%; float:left; background:#ddd; }
此時運行看一下結果:
因為現在已經改成流式布局了,所以容器的寬度會隨着瀏覽器的寬度而按比例縮放。當然,需要配合浮動或者定位。
但是CSS3提供了一種更好的彈性伸縮布局flexbox,看看怎么實現:
.wrap{ width:80%; height:400px; border:1px solid red; margin:0 auto; display:flex; } .left{ flex:2; background:#ccc; } .right{ flex:3; background:#ddd; }
是不是更簡單。所以說,不管多少欄布局(實際開發中也不會很多欄的),通過流式布局或者flexbox彈性伸縮布局基本能解決。但目前來說,彈性布局兼容性還不是很好,所以用得比較多的還是移動端布局,但總體上更多的還是使用流式布局,必要時可以配合媒體查詢。
既有固定布局也有自適應布局
還是上面的實例,現在兩欄布局第一個子元素固定寬度,而第二個子元素自適應剩余的寬度,該怎么做?
第一種方法就是給第二個子元素加左外邊距,擠出來:
.wrap{ width:80%; height:400px; border:1px solid red; margin:0 auto; } .left{ width:200px; height:300px; float:left; background:#ccc; } .right{ height:100%; margin-left:200px; background:#ddd; }
結果就是這樣的:
第二種方法就是絕對定位+外邊距:
.wrap{ width:80%; height:400px; border:1px solid red; margin:0 auto; position:relative; } .left{ width:200px; height:300px; background:#ccc; position: absolute; top:0; left:0; } .right{ height:100%; background:#ddd; margin-left:200px; }
但其實第一種方法和第二種方法原理是一樣的,換湯不換葯罷了。
第三種方法,利用BFC特性:
.wrap{ width:80%; height:400px; border:1px solid red; margin:0 auto; } .left{ width:200px; height:300px; background:#ccc; float:left; } .right{ height:100%; background:#ddd; overflow: hidden; }
這里給第二個子元素設置了overflow:hidden之后呢,它就生成了一個BFC塊,BFC其中的一個布局規則就是不會和float box 發生重疊,於是就和第一個浮動了的子元素隔開了,我說得比較蒼白,大家可以去多了解BFC的一些布局特性,包括如何生成一個新的BFC塊。那為了方便,我這里就把BFC的一些相關知識點直接放上來給大家了解一下:
BFC布局規則:
- 內部的Box會在垂直方向,一個接一個地放置。
- Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊
- 每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此。
- BFC的區域不會與float box重疊。
- BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。
- 計算BFC的高度時,浮動元素也參與計算
哪些元素會生成BFC:
- 根元素
- float屬性不為none
- position為absolute或fixed
- display為inline-block, table-cell, table-caption, flex, inline-flex
- overflow不為visible
OK,還有一種方法就是flex布局:
.wrap{ width:80%; height:400px; border:1px solid red; margin:0 auto; display:flex; } .left{ width:200px; height:300px; background:#ccc; } .right{ height:100%; background:#ddd; flex:1; }
是不是也挺方便的?現在我提升一下難度,現在是三欄布局,左右欄固定寬度,中間自適應,該怎么做?
這時候flex布局就是最佳的選擇了:
.wrap{ width:80%; height:400px; border:1px solid red; margin:0 auto; display:flex; } .left{ width:200px; height:300px; float:left; background:#ccc; } .right{ width:200px; height:300px; float:right; background:#ddd; } .center{ height:100%; background:#666; flex:1; }
這種本來就很苦惱的布局,對於flex布局來說都能輕松解決意外煩惱。
且慢,如果我想讓中間的子元素優先渲染呢?
<div class="wrap"> <div class="center">中間自適應欄</div> <div class="left">左邊固定欄</div> <div class="right">右邊固定欄</div> </div>
這時的情況是這樣的:
這時候吧,還是得利用flex來解決這個問題:
.wrap{ width:80%; height:400px; border:1px solid red; margin:0 auto; display:flex; } .left{ width:200px; height:300px; float:left; background:#ccc; order:1; } .right{ width:200px; height:300px; float:right; background:#ddd; order:3; } .center{ height:100%; background:#666; flex:1; order:2; }
這時候出來的效果就是我們想要的:
好的,關於多欄自適應布局我就講到這里,其他方面的知識擴展與應用,就留給大家去研究了。
二、水平垂直居中
水平居中最常用的就是text-align:center; 和 margin:0 auto; 其中text-align:center;是對內部子元素(inline/inline-block)起作用,而margin:0 auto;是對元素自身(block)起作用,具體根據自己的需要適當地運用。
垂直居中常用的有line-height 和 vertical-align:middle,但是它們都有使用的限制條件或者前提吧。比如line-height得和height一樣高,vertical-align:middle 只對inline-block起作用,但其實還有很多坑,個人不怎么喜歡使用vertical-align。
下面我們就直接進入水平垂直居中的討論吧:
其實吧,水平垂直居中也是有兩種情況:知道寬高 和 不知道寬高。
1.已知寬高的水平垂直居中
在這種情況下,其實就很好解決了,實例說明一下:
html代碼:
<div class="wrap"> <div class="child">水平垂直居中</div> </div>
默認樣式:
.wrap{ width:400px; height:400px; border:1px solid red; margin:0 auto; } .child{ width:200px; height:200px; background:#ccc; }
現在的情況是這樣的:
因為我們是已知寬高的,所以可以給子元素加外邊距擠到中間位置,或者通過絕對定位到中間位置,當然還有一些方法,我就放在未知寬高的情況下再介紹,因為已知寬高包含於未知寬高,所以為了避免重復,我就分開了,這里就只講僅適合已知寬高的情況。
我們給子元素加上外邊距:
.child{ margin-top:100px; margin-left:100px; }
這時內部子元素就水平垂直居中了。
現在使用絕對定位來實現:
.wrap{ position:relative; } .child{ position:absolute; top:50%; left:50%; margin-top:-100px; margin-left:-100px; }
貌似絕對定位比較麻煩,但其實絕對定位對整體布局更好一些,也是比較常用。
2.未知寬高的水平垂直居中
1.絕對定位+css3 transform:translate(-50%,-50%)
.wrap{ position:relative; } .child{ position: absolute; top:50%; left:50%; -webkit-transform:translate(-50%,-50%); }
2.css3 的flex布局
.wrap{ display:flex; justify-content:center; } .child{ align-self:center; }
3.table布局
<div class="wrap"> <div class="child"> <div>sadgsdgasgd</div> </div> </div>
.wrap{ display:table; text-align:center; } .child{ background:#ccc; display:table-cell; vertical-align:middle; } .child div{ width:300px; height:150px; background:red; margin:0 auto; }
table布局貌似得多套一層,試了好多遍,兩層都出不來效果。但是這種html結構太冗余了。所以前兩種比較新潮一些。
OK,水平垂直居中就講到這里,以上都是自己琢磨的一些方法,有什么紕漏或者不恰當的地方,歡迎留言指正。
三、清除浮動
這里就不講為什么我們要清楚浮動,反正不清除浮動事多多。
下面我就講三種常用清除浮動的方法,夠用了。
1.在浮動元素后面加一個空的div,並為它清除浮動
html代碼:
<div class="wrap"> <div class="float">浮動</div> <div class="clear"></div> <div class="nofloat">不想被浮動影響</div> </div>
css代碼:
.wrap{ width:500px; height:400px; border:1px solid red; margin:0 auto; } .float{ width:200px; height:200px; background:#ccc; float:left; } .nofloat{ width:300px; height:150px; background:red; }
現在雖然加了一個空的div,但是並沒有給它清除浮動,所以目前的效果就是第三個子元素.nofloat還是收到浮動的影響。
OK,現在給.clear加上清除浮動:
.clear{ clear:both; }
刷新一下效果就出來了:
PS:這種情況比較適合元素之間是垂直排列布局的,為了不受彼此浮動的影響。
2.利用BFC特性清除浮動
html代碼:
<div class="wrap"> <div class="float">浮動</div> <div class="nofloat">不想被浮動影響</div> </div>
css代碼:
.wrap{ width:500px; border:1px solid red; margin:0 auto; overflow:hidden; } .float{ width:200px; height:200px; background:#ccc; float:left; } .nofloat{ width:300px; height:150px; background:red; overflow:hidden; }
效果是這樣的:
這里父容器是沒有設置固定高度的,本來第一個子元素浮動之后,父元素的高度會塌陷到跟第二個子元素一樣高,但由於這里分別給第二個子元素和父元素都設置了overflow:hidden ,所以它們都生成了一個新的BFC區域,根據上文提供的BFC布局規則可以得知:BFC區域不會與float box 重疊;計算BFC高度時浮動元素的高度也參與計算。所以就得到清除浮動的效果。說得比較繞,但其實清除浮動得根據自己開發中的實際情況合理使用。
3.使用:after偽元素,給浮動元素的父元素清除浮動
html代碼:
<div class="wrap"> <div class="float">浮動</div> </div>
css代碼:
.wrap{ width:500px; border:1px solid red; margin:0 auto; } .float{ width:200px; height:200px; background:#ccc; float:left; }
此時子元素浮動了,脫離了文檔流,所以父元素高度酒塌陷了:
可以看到父元素的邊框擠在一起了。
OK,現在給父元素添加一個clearfix類:
<div class="wrap clearfix"> <div class="float">浮動</div> </div>
.clearfix{ *zoom:1; } .clearfix:after{ content:'clear'; display:block; height:0; clear:both; overflow:hidden; visibility:hidden; }
現在刷新后的效果就是:
這種方法和BFC清除浮動個人用的比較多,實際開發中,其實這兩種就夠用了。
好的,清除浮動我也就簡單地提到這里!
總結
以上我總結了自己對標題中列出的三個知識點——(多欄自適應布局,水平垂直居中,清除浮動)的一些個人積累。如果有什么錯誤的話,歡迎留言指正。
若需轉載,請注明出處,謝謝合作!