這可能是史上最全的CSS自適應佈局總結教程

這可能是史上最全的CSS自適應佈局總結教程

標題嚴格遵守了新廣告法,你再不爽,我也沒犯法呀!話不多說,直入正題。

所謂佈局,其實包含兩個含義:尺寸與定位。也就是說,所有與尺寸和定位相關的屬性,都可以用來佈局。

大體上,佈局中會用到的有:尺寸相關的盒子模型,普通流、浮動、絕對定位三種定位機制,CSS3中的transform、彈性盒子模塊、試驗中的grid模塊。逛園子的時候經常可以看到浮動佈局,inline-block佈局,彈性盒佈局這幾個名詞。現在對佈局也算有一點了解,做個總結鞏固一下。如果你也看了很多資料,但是實際動手時對佈局還是無從下手的話,希望本文可以幫你理清思路。

嘮叨一句:看到一個效果圖的時候,千萬不要急着手賤去敲代碼!先思考清楚頁面的構造,理清各元素之間的關係,特別需要注意的是在不同的設備下需要有怎樣的展現,當你思路清晰找到最好的佈局方案時,coding其實真的不需要多少時間。

 

尺寸相關


爲什麼要先說尺寸呢?因爲尺寸在佈局中的作用非常核心,佈局方式定位這些只是改變了元素之間的關係,沒有尺寸就什麼也不是。比如我們通常會用margin來控制跟其他元素的距離,這就是佈局。

很多人都會覺得,什麼width、margin太簡單了,早就掌握了。這種心態我一開始學習CSS的時候也有,覺得很好理解很簡單,但是後面才發現自己原來很多東西都沒真正掌握。看看張鑫旭大神給我們上的政治課:http://www.zhangxinxu.com/wordpress/2012/07/bottleneck-css-study/ 

先說說百分比,百分比是相對父對象的,這裏特性非常好用,很多時候會用在自適應佈局上面。瀏覽器尺寸的改變,就是根節點html的長寬改變,我們可以用%來將瀏覽器尺寸和元素尺寸聯繫起來,做到自適應。

另外一個比較有意思的是auto,auto是很多尺寸值的默認值,也就是由瀏覽器自動計算。首先是塊級元素水平方向的auto,塊級元素的margin、border、padding以及content寬度之和等於父元素width。使用auto屬性在父元素寬度變化的時候,該元素的寬度也會隨之變化。

auto

但是當該元素被設爲浮動時,該元素的width就變成了內容的寬度了,由內容撐開,也就是所謂的有了包裹性。overflow | position:absolute | float:left/right都可以產生包裹性,替換元素也同樣具有包裹性。在具有包裹性的元素上想利用width : auto;來讓元素寬度自適應瀏覽器寬是不行的。

包裹性

高度方向:外邊距重疊,外邊距auto爲0,這兩點需要注意。書寫方向什麼的,接觸比較少就不扯了。

那爲什麼margin:auto對不能計算垂直方向的值呢?很簡單,垂直方向是被設計成可以無限擴展的,內容越多瀏覽器便產生滾動條來擴展,所以垂直方向都找不到一個計算基準,以此返回一個false,便成了0。

用處:通過width、height控制大小,各個方向的margin值控制與邊界或者其他元素的距離來定位。

 

浮動


目前PC網站大多使用float佈局,從成本上考慮大改的概率很小,所以不要說浮動無用,總是會有機會讓你維護的!代表網站:淘寶、騰訊、百度,好吧BAT都到齊了。

浮動聽得多了,博客園上關於用浮動佈局的介紹也非常的多。浮動原本用於文本環繞,但卻在佈局被發揚光大,這就是命!我的理解:浮動佈局的核心就是讓元素脫離普通流,然後使用width/height,margin/padding將元素定位。脫離普通流的元素,就像脫離地心引力一樣,與普通流不在一個高度上。這個跟圖層的概念類似。高度不同所以可以疊在其他元素上面產生重疊或者使用負邊距跑到父元素外,理解了這一點浮動佈局就很好理解了。

圖層

下面用個聖盃佈局的例子說明一下,理解了這個之後其他佈局更加簡單:

left,寬度固定,高度可固定也可由內容撐開
right,寬度固定,高度可固定也可由內容撐開
center,可以自適應瀏覽器寬度,高度可固定也可由內容撐開。

HTML & CSS:

複製代碼
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>寬度自適應佈局</title>
        <style>
            .wrap {
                background-color: #D66464;
            }
            .clearfix:after {
                content: "";
                clear: both;
                display: block;
            }
            .left {
                float: left;
                width: 100px;
                background: #00f;
                height: 180px;
            }
            .right {
                float: right;
                width: 150px;
                background: #0f0;
                height: 200px;
            }
            .center {
                background: #FFFFFF;
                margin-left: 110px;
                margin-right: 160px;
                height: 150px;
            }
        </style>
    </head>
    <body>
        <div class="wrap clearfix">
            <div class="left">left,寬度固定,高度可固定也可以由內容撐開。</div>
            <div class="right">right,寬度固定,高度可固定也可以由內容撐開。</div>
            <div class="center">center,可以自適應瀏覽器寬度,高度可固定也可以由內容撐開。</div>
        </div>
    </body>
</html>
複製代碼
View Code

原理非常簡單,左右側邊欄定寬並浮動,中部內容區放最後不浮動、默認width:auto並設置相應外邊距,讓左右側邊欄浮動到上面。注意:子元素設置爲浮動之後,父對象的高度就坍塌了,需要設置父對象後的元素清除浮動,這樣父對象的高度才能被浮動子元素撐起來了。

當然,我們也要問一下,爲啥父對象高度會坍塌呢?上面也說過了,浮動元素已經脫離了普通流,父對象所在的普通流比喻成地表,那浮動元素就已經上天了。但是父對象還在地表啊,從外太空看浮動元素在父對象裏面,但是其實並不在,又怎麼能撐開父對象呢?寬度如果我們不設置的話,其實也是爲0的,因爲父對象裏面空空如也,所以寬高爲0。

上天

要撐開的辦法就兩個,1是讓父對象也上天(。。。你咋不上天呢),2是把浮動元素的邊框邊界拉下來。

父對象也上天(即浮動)的話,那就不能實現寬度自適應了。因爲float元素的width:auto是包裹內容的,參考前面說的!

辦法2就是在後面的元素里加一個clear語句。說到這個問題就要扯到clear與BFC了,我就不獻醜了。傳送門:https://developer.mozilla.org/zh-CN/docs/Web/CSS/clear

這個三列布局還有個雙飛(是雙飛翼!想啥呢)的變種,就是在HTML中center部分也就是內容區提到最前面,也就是內容先行渲染。在網絡不好的時候,左右雙翼能不能出來不要緊,先讓主體內容出來!這種想法,明顯的優秀工程師思維,但,尼瑪的雙翼都是廣告啊。廣告不出來,哪能賺錢養你們這羣工程師?所以提出雙飛的玉伯才離開了淘寶???(純屬意淫,如真屬實,當我扯淡,哈哈哈!)

哈哈哈

先上碼:

複製代碼
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>寬度自適應佈局</title>
        <style>
            .wrap {
                background-color: #FBD570;
                margin-left: 100px;
                margin-right: 150px;
            }
            .clearfix:after {
                content: "";
                clear: both;
                display: block;
            }
            .left {
                float: left;
                width: 100px;
                background: #00f;
                height: 180px;
                margin-left: calc(-100% - 100px); 
            }
            .right {
                float: right;
                width: 150px;
                background: #0f0;
                height: 200px;
                margin-right: -150px;
            }
            .center {
                background: #B373DA;
                height: 150px;
                float: left;
                width: 100%;
            }
        </style>
    </head>
    <body>
        <div class="wrap clearfix">
            <div class="center">center,可以自適應瀏覽器寬度,高度可固定也可以由內容撐開。</div>
            <div class="left">left,寬度固定,高度可固定也可以由內容撐開</div>
            <div class="right">right,寬度固定,高度可固定也可以由內容撐開</div>
        </div>
    </body>
</html>
複製代碼
View Code

思路:

1)既然HTML裏面要讓center放前面,爲了讓left跑到center前面,那center也必須浮動了,否則因爲都是塊元素他們會分兩行。

2)浮動之後還要讓center寬度自適應,那明顯width只能100%,然後在父元素中設width:auto,還有兩側margin,其實也就是父對象寬度自適應,center只是繼承content的寬度。

3)對left使用負的margin讓他們浮動到上方去。

代碼裏面我用到了一個calc(),這個CSS3帶來的計算函數簡直酷斃了!本例裏如果不使用calc函數,那麼就需要wrap左邊距爲0,left左邊距-100%,然後center多加一層子塊DIV設置margin-left:100px,可以達到同樣的效果!calc函數與百分比配合就足以實現自適應的要求!目前所有的自適應佈局都在利用瀏覽器來爲我們計算尺寸,但是有了calc之後我們就可以自己制定規則!單是想想都高潮了吧?

總結:使用浮動來進行佈局,一個比較大的問題是清除浮動。這個可以使用一個after僞類來清除。更大的問題是浮動性像水一樣向上流動,難以把握。在元素較多而且元素高度尺寸不一的情況下,單純使用浮動只能實現上端對齊,這對於適應多種設備的佈局就顯得力不從心了。目前的做法是犧牲一部分內容,將元素做成等高排列,從美觀上看也當然也是極好的,比參差不齊的排列要美觀。

 

普通流佈局


普通流佈局:display : inline-block!這是一個傳說中取代float佈局的存在。看了一些網站,PC端浮動爲主,移動端的也用的不多啊,已經有些使用flex的了,說好的inline-block一統江湖呢?

使用inline-block之前先處理點小障礙:inline-block元素會有4px左右的空隙,這個是因爲我們寫代碼時候的換行符所致。

4px間隙

解決辦法很簡單:在inline-block的父元素中設置樣式font-size:0;letter-spacing: -4px; 然後設置inline-block的所有兄弟元素 font-size:值;letter-spacing: 值px;  恢復正常的顯示。

消除4px間隙

另外還有一點需要注意的是inline-block默認是基線對齊的,而inline-block的基線又跟文本基線一致,所以在內容不同的時候並不能水平對齊。只需要用vertical-align顯式聲明一下top/bottom/middle對齊即可。這裏補充一下基線的內容,沒你想的那麼簡單哦。分有文字和無文字兩種情況:

1)無文字:容器的margin-bottom下邊緣。與容器內部的元素沒一毛錢關係。

2)有文字:最後一行文字的下邊緣,跟文字塊(p,h等)的margin、padding沒關係!注意是最後一行,無論文字在什麼子對象容器內在什麼位置都沒關係,瀏覽器會找到最後一行文字對齊底部。

你們感受一下:

baseline-01    baseline-02    baseline-03

警示:inline-block的基線是最後一行文字的底部,flex裏面的基線是第一行文字的底部(請看下文阮老師的文章)

baseline-04

滿滿的都是淚啊。。。既然都叫baseline,何必呢?

ohmygod

使用inline-block進行聖盃佈局:

複製代碼
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>寬度自適應佈局</title>
        <style>
            .wrap {
                background-color: #FBD570;
                font-size: 0;
                letter-spacing: -4px;  /*用於兼容safari,根據不同字體字號或許需要做一定的調整*/
                margin-left: 100px;
                margin-right: 150px;
            }
            .wrap * {
                font-size: 1rem;
                letter-spacing: normal;
            }
            .left {
                display: inline-block;
                vertical-align: top;
                width: 100px;
                background: #00f;
                height: 180px;
                margin-left: -100px;
            }
            .right {
                display: inline-block;
                vertical-align: top;
                   width: 150px;
                background: #0f0;
                height: 200px;
                margin-right: -150px;
            }
            .center {
                display: inline-block;
                vertical-align: top;
                background: #B373DA;
                height: 150px;
                min-width: 150px;
                width: 100%;
            }
        </style>
    </head>
    <body>
        <div class="wrap">
            <div class="left">left,寬度高度固定</div>
            <div class="center">center,可以自適應瀏覽器寬度,高度固定。</div>
            <div class="right">right,寬度高度固定</div>
        </div>
    </body>
</html>
複製代碼
View Code

這裏也沒什麼好說的,用到的也是width:auto和width:100%這兩點,簡單知識點的簡單用法。

雙飛的話,代碼跟聖盃的基本相同,注意在html的順序變爲center>right>left,只改左欄移動的margin-left: calc(-100% - 100px)到預定位置即可。不能用calc的話可以在center裏面再加一層,跟浮動一樣的處理方式。更簡單的方法是使用CSS3帶給我們的box-sizing屬性。請看代碼:

複製代碼
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>寬度自適應佈局</title>
        <style>
            .wrap {
                background-color: #FBD570;
                font-size: 0;
                letter-spacing: -4px;  /*用於兼容safari,根據不同字體字號或許需要做一定的調整*/
                margin-right: 150px;
            }
            .wrap * {
                font-size: 1rem;
                letter-spacing: normal;
            }
            .left {
                display: inline-block;
                vertical-align: top;
                width: 100px;
                background: #00f;
                height: 180px;
                margin-left: -100%;
            }
            .right {
                display: inline-block;
                vertical-align: top;
                   width: 150px;
                background: #0f0;
                height: 200px;
                margin-right: -150px;
            }
            .center {
                display: inline-block;
                vertical-align: top;
                background: #B373DA;
                height: 150px;
                min-width: 150px;
                width: 100%;
                box-sizing: border-box;
                padding-left: 100px;
                background-origin: content-box;
                background-clip: content-box;
            }
        </style>
    </head>
    <body>
        <div class="wrap">
            <div class="center">
                center,可以自適應瀏覽器寬度,高度固定。
            </div>
            <div class="right">right,寬度高度固定</div>
            <div class="left">left,寬度高度固定</div>
        </div>
    </body>
</html>
複製代碼
View Code

總結:相比浮動inline-block更加容易理解,也更符合我們的認知,結合盒子模型的幾個控制屬性就可以進行佈局了。對於元素高度不同的情況,目前浮動佈局的做法都是將元素做成等高元素進行展現,這從美學上看也符合整齊的要求,不過犧牲了一部分內容。但inline-block有vertical-align屬性,可以很好地解決元素高度不同而帶來的佈局問題。用過之後,你也會喜歡上inline-block的。。。至少我會!

 

絕對定位


前面的浮動和普通流中其實定位都是靠盒子模型控制的,與我們常說的定位還是有差別的。而絕對定位就是我們平常所說的定位,給定參考座標系+座標確定位置。關於絕對定位的資料太多,我就不說了。提一點就是absolute定位的基準是最近的非static定位父對象,而fixed是相對html根節點的定位。兩種定位都會脫離普通流,跟之前說的浮動一樣,上天了。

上天

當然,他們跟浮動在空間中的位置還是有差別的,項目中有遇到這個問題的請參考張大嬸的文章: http://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/  還是要結合項目來看,否則看過也只是看過而已,並不會存到你的腦子裏,畢竟還是相當抽象相當理論性的東西。借用張大神的一個總結圖:

2016-01-07_223349

使用絕對定位(特指absolute)做自適應佈局跟前面兩種方式沒太大差別,寬度自適應還是在auto和100%上做文章,而位置則由top/bottom/left/right等控制。還是以聖盃佈局來舉例:

複製代碼
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>寬度自適應佈局</title>
        <style>
            .wrap {
                position: relative;
                background-color: #FBD570;
                margin-left: 100px;
                margin-right: 150px;
                height: 250px;
            }
            .left {
                position: absolute;
                top: 0;
                left: -100px;
                width: 100px;
                background: #00f;
                height: 180px;
            }
            .right {
                position: absolute;
                top: 0;
                right: 0;
                   width: 150px;
                background: #0f0;
                height: 200px;
                margin-right: -150px;
            }
            .center {
                position: absolute;
                top: 0;
                left: 0;
                background: #B373DA;
                height: 150px;
                min-width: 150px;
                width: 100%;
            }
        </style>
    </head>
    <body>
        <div class="wrap">
            <div class="center">
                center,可以自適應瀏覽器寬度,高度固定。
            </div>
            <div class="left">left,寬度高度固定</div>
            <div class="right">right,寬度高度固定</div>
        </div>
    </body>
</html>
複製代碼
View Code

父元素爲relative,子元素爲absolute,這樣的話,又會出現跟浮動一樣的問題:父對象高度坍塌,子元素不能撐起父對象。原因也跟浮動一樣,解決辦法的話目前我知道的只有給父對象指定一個確定height值,大家如果有更好的辦法,請聯繫我!

總結:單純使用絕對定位進行自適應佈局的情況很少,一般絕對定位都用在尺寸固定的元素定位上。而且fixed定位的渲染效率很低,因爲它會頻繁觸發瀏覽器的重排。另外提一點:CSS3的transform會對絕對定位產生影響哦~比如說讓fixed定位不再固定在瀏覽器視窗的黑魔法:http://www.zhangxinxu.com/wordpress/2015/05/css3-transform-affect/ 

 

彈性盒子


CSS3中對佈局影響最大的莫過於彈性盒子模塊了,這是一套區別於以往盒子模型佈局的全新方案。上面幾種方法你可以看到,爲了實現自適應我們用的都是width:auto和100%的嵌套以及各種邊距的移動定位,這套規則並不符合我們的認知。爲什麼不能開拓出一塊區域,橫豎排列都可以,內部所有元素的尺寸可以按照一個規則和這個區域的大小聯繫起來?終於CSS3做出了改變,引入了flex彈性佈局方案,彈性盒佈局有如下優勢:
       1.獨立的高度控制與對齊。
       2.獨立的元素順序。
       3.指定元素之間的關係。
       4.靈活的尺寸與對齊方式。

在MDN上有非常簡單易懂的基礎教程:https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes

flexbox

上面也已經給出了聖盃佈局的自適應佈局方案,所以代碼就不貼了不過這個例子實現的是3欄成比例縮放,左右欄如果需要固定值的話可以寫成  flex: 0 0 150px; 的樣式。

但是上面的教程沒有給出各個屬性的詳細解釋,建議看看阮一峯的博文,詳細易懂而且配圖超漂亮的有木有:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

總結:彈性盒子在移動端的應用會越來越普遍,這套模型值得去好好研究。語法規則都是非常貼近人性,非常靈活,瀏覽器兼容性也非常好,當然國內百花齊放的移動瀏覽器會有哪些大坑呢?我們拭目以待~

 

其他


其他包括position:relative和CSS3中的transform都可以實現定位,但是由於他們在原來的普通流中還佔着一個坑,所以很少用來佈局啥的。transform是個很酷炫的東西,可以用平面的素材做出很多3D的效果,而且不需要js就可以做,非常好玩。此文已經很長,就不多說了,以後會寫一篇文章來專門說說她的故事。


轉載:!本文鏈接:http://www.cnblogs.com/qieguo/p/5421252.html 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章