CSS樣式----浮動(圖文詳解)

本文最初發表於博客園,並在GitHub上持續更新。如下是正文。css

標準文檔流

宏觀地講,咱們的web頁面和photoshop等設計軟件有本質的區別:web頁面的製做,是個「流」,必須從上而下,像「織毛衣」。而設計軟件,想往哪裏畫個東西,都能畫。html

標準文檔流的特性

咱們來看看標準流有哪些微觀現象。前端

(1)空白摺疊現象:git

不管多少個空格、換行、tab,都會摺疊爲一個空格。github

好比,若是咱們想讓img標籤之間沒有空隙,必須緊密鏈接:web

<img src="images/0.jpg" /><img src="images/1.jpg" /><img src="images/2.jpg" />

(2)高矮不齊,底邊對齊:面試

舉例以下:瀏覽器

(3)自動換行,一行寫不滿,換行寫。微信

塊級元素和行內元素

學習的初期,咱們就要知道,標準文檔流等級森嚴。標籤分爲兩種等級:佈局

  • 行內元素
  • 塊級元素

咱們能夠舉一個例子,看看塊級元素和行內元素的區別:

上圖中能夠看到,h1標籤是塊級元素,佔據了整行,span標籤是行內元素,只佔據內容這一部分。

如今咱們嘗試給兩個標籤設置寬高。效果以下:

上圖中,咱們嘗試給兩個標籤設置寬高,但發現,寬高屬性只對塊級元素h1生效。因而咱們能夠作出以下總結。

行內元素和塊級元素的區別:(很是重要)

行內元素:

  • 與其餘行內元素並排;
  • 不能設置寬、高。默認的寬度,就是文字的寬度。

塊級元素:

  • 霸佔一行,不能與其餘任何元素並列;
  • 能接受寬、高。若是不設置寬度,那麼寬度將默認變爲父親的100%。

塊級元素和行內元素的分類:

在之前的HTML知識中,咱們已經將標籤分過類,當時分爲了:文本級、容器級。

從HTML的角度來說,標籤分爲:

  • 文本級標籤:p、span、a、b、i、u、em。
  • 容器級標籤:div、h系列、li、dt、dd。

PS:爲甚麼說p是文本級標籤呢?由於p裏面只能放文字&圖片&表單元素,p裏面不能放h和ul,p裏面也不能放p。

如今,從CSS的角度講,CSS的分類和上面的很像,就p不同:

  • 行內元素:除了p以外,全部的文本級標籤,都是行內元素。p是個文本級,可是是個塊級元素。

  • 塊級元素:全部的容器級標籤都是塊級元素,還有p標籤。

咱們把上面的分類畫一個圖,便可一目瞭然:

塊級元素和行內元素的相互轉換

咱們能夠經過display屬性將塊級元素和行內元素進行相互轉換。display即「顯示模式」。

塊級元素能夠轉換爲行內元素:

一旦,給一個塊級元素(好比div)設置:

display: inline;

那麼,這個標籤將當即變爲行內元素,此時它和一個span無異。inline就是「行內」。也就是說:

  • 此時這個div不能設置寬度、高度;
  • 此時這個div能夠和別人並排了。

舉例以下:

行內元素轉換爲塊級元素:

一樣的道理,一旦給一個行內元素(好比span)設置:

display: block;

那麼,這個標籤將當即變爲塊級元素,此時它和一個div無異。block」是「塊」的意思。也就是說:

  • 此時這個span可以設置寬度、高度
  • 此時這個span必須霸佔一行了,別人沒法和他並排
  • 若是不設置寬度,將撐滿父親

舉例以下:

標準流裏面的限制很是多,致使不少頁面效果沒法實現。若是咱們如今就要並排、而且就要設置寬高,那該怎麼辦呢?辦法是:移民!脫離標準流

css中一共有三種手段,使一個元素脫離標準文檔流:

  • (1)浮動
  • (2)絕對定位
  • (3)固定定位

這便引出咱們今天要講的內容:浮動。

浮動

浮動是css裏面佈局用的最多的屬性。

如今有兩個div,分別設置寬高。咱們知道,它們的效果以下:

此時,若是給這兩個div增長一個浮動屬性,好比float: left;,效果以下:

這就達到了浮動的效果。此時,兩個元素並排了,而且兩個元素都可以設置寬度、高度了(這在上一段的標準流中,不能實現)。

浮動想學好,必定要知道三個性質。接下來說一講。

性質1:浮動的元素脫標

脫標即脫離標準流。咱們來看幾個例子。

證實1:

上圖中,在默認狀況下,兩個div標籤是上下進行排列的。如今因爲float屬性讓上圖中的第一個<div>標籤出現了浮動,因而這個標籤在另一個層面上進行排列。而第二個<div>還在本身的層面上聽從標準流進行排列。

證實2:

上圖中,一個span標籤不須要轉成塊級元素,就可以設置寬度、高度了。因此可以證實一件事兒,就是全部標籤已經不區分行內、塊了。也就是說,一旦一個元素浮動了,那麼,將可以並排了,而且可以設置寬高了。不管它原來是個div仍是個span。

性質2:浮動的元素互相貼靠

咱們來看一個例子就明白了。

咱們給三個div均設置了float: left;屬性以後,而後設置寬高。當改變瀏覽器窗口大小時,能夠看到div的貼靠效果:

上圖顯示,3號若是有足夠空間,那麼就會靠着2號。若是沒有足夠的空間,那麼會靠着1號大哥。
若是沒有足夠的空間靠着1號大哥,3號本身去貼左牆。

不過3號本身去貼牆的時候,注意:

上圖顯示,3號貼左牆的時候,並不會往1號裏面擠。

一樣,float還有一個屬性值是right,這個和屬性值left是對稱的。

性質3:浮動的元素有「字圍」效果

來看一張圖就明白了。咱們讓div浮動,p不浮動。

上圖中,咱們發現:div擋住了p,但不會擋住p中的文字,造成「字圍」效果。

關於浮動咱們要強調一點,浮動這個東西,爲避免混亂,咱們在初期必定要遵循一個原則:永遠不是一個東西單獨浮動,浮動都是一塊兒浮動,要浮動,你們都浮動。

性質4:收縮

收縮:一個浮動的元素,若是沒有設置width,那麼將自動收縮爲內容的寬度(這點很是像行內元素)。

舉例以下:

上圖中,div自己是塊級元素,若是不設置widh,它會單獨霸佔整行;可是,設置div浮動後,它會收縮

浮動的補充(作網站時注意)

上圖所示,將para1和para2設置爲浮動,它們是div的兒子。此時para1+para2的寬度小於div的寬度。效果如上圖所示。可若是設置para1+para2的寬度大於div的寬度,咱們會發現,para2掉下來了:

佈置一個做業

佈置一個做業,要求實現下面的效果:

爲實現上方效果,代碼以下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>Document</title>
    <style type="text/css">
        *{
            margin: 0;
            padding: 0;
        }
        .header{
            width: 970px;
            height: 103px;
            /*居中。這個語句的意思是:居中:*/
            margin: 0 auto;
        }
        .header .logo{
            float: left;
            width: 277px;
            height: 103px;
            background-color: red;
        }
        .header .language{
            float: right;
            width: 137px;
            height: 49px;
            background-color: green;
            margin-bottom: 8px;
        }
        .header .nav{
            float: right;
            width: 679px;
            height: 46px;
            background-color: green;
        }

        .content{
            width: 970px;
            height: 435px;
            /*居中,這個語句今天沒講,你照抄,就是居中:*/
            margin: 0 auto;
            margin-top: 10px;
        }
        .content .banner{
            float: left;
            width: 310px;
            height: 435px;
            background-color: gold;
            margin-right: 10px;
        }
        .content .rightPart{
            float: left;
            width: 650px;
            height: 435px;
        }
        .content .rightPart .main{
            width: 650px;
            height: 400px;
            margin-bottom: 10px;
        }
        .content .rightPart .links{
            width: 650px;
            height: 25px;
            background-color: blue;
        }
        .content .rightPart .main .news{
            float: left;
            width: 450px;
            height: 400px;
        }
        .content .rightPart .main .hotpic{
            float: left;
            width: 190px;
            height: 400px;
            background-color: purple;
            margin-left: 10px;
        }
        .content .rightPart .main .news .news1{
            width: 450px;
            height: 240px;
            background-color: skyblue;
            margin-bottom: 10px;
        }
        .content .rightPart .main .news .news2{
            width: 450px;
            height: 110px;
            background-color: skyblue;
            margin-bottom: 10px;
        }
        .content .rightPart .main .news .news3{
            width: 450px;
            height: 30px;
            background-color: skyblue;
        }
        .footer{
            width: 970px;
            height: 35px;
            background-color: pink;
            /*沒學,就是居中:*/
            margin: 0 auto;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <!-- 頭部 -->
    <div class="header">
        <div class="logo">logo</div>
        <div class="language">語言選擇</div>
        <div class="nav">導航條</div>
    </div>

    <!-- 主要內容 -->
    <div class="content">
        <div class="banner">大廣告</div>
        <div class="rightPart">
            <div class="main">
                <div class="news">
                    <div class="news1"></div>
                    <div class="news2"></div>
                    <div class="news3"></div>
                </div>
                <div class="hotpic"></div>
            </div>
            <div class="links"></div>
        </div>
    </div>

    <!-- 頁尾 -->
    <div class="footer"></div>
</body>
</html>

其實,這個頁面的佈局是下面這個網站:

浮動的清除

這裏所說的清除浮動,指的是清除浮動與浮動之間的影響。

前言

經過上面這個例子,咱們發現,此例中的網頁就是經過浮動實現並排的。

好比說一個網頁有header、content、footer這三部分。就拿content部分來舉例,若是設置content的兒子爲浮動,可是,這個兒子又是一個全新的標準流,因而兒子的兒子仍然在標準流裏。

從學習浮動的第一天起,咱們就要明白,浮動有開始,就要有清除。咱們先來作個實驗。

下面這個例子,有兩個塊級元素div,div沒有任何屬性,每一個div裏有li,效果以下:

上面這個例子很簡單。可若是咱們給裏面的<li>標籤加浮動。效果卻成了下面這個樣子:

代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
        *{

        }
        li{
            float: left;
            width: 100px;
            height: 20px;
            background-color: pink;


        }
    </style>
</head>
<body>
    <div class="box1">
        <ul>
            <li>生命壹號1</li>
            <li>生命壹號2</li>
            <li>生命壹號3</li>
            <li>生命壹號4</li>
        </ul>
    </div>
    <div class="box2">
        <ul>
            <li>許嵩1</li>
            <li>許嵩2</li>
            <li>許嵩3</li>
            <li>許嵩4</li>
        </ul>
    </div>  
</body>
</html>

效果以下:

上圖中,咱們發現:第二組中的第1個li,去貼靠第一組中的最後一個li了(咱們本覺得這些li會分紅兩排)。

這便引出咱們要講的:清除浮動的第一種方式。
那該怎麼解決呢?

方法1:給浮動元素的祖先元素加高度

形成前言中這個現象的根本緣由是:li的父親div沒有設置高度,致使這兩個div的高度均爲0px(咱們能夠經過網頁的審查元素進行查看)。div的高度爲零,致使不能給本身浮動的孩子,撐起一個容器。

撐不起一個容器,致使本身的孩子沒辦法在本身的內部進行正確的浮動。

好,如今就算給這個div設置高度,可若是div本身的高度小於孩子的高度,也會出現不正常的現象:

給div設置一個正確的合適的高度(至少保證高度大於兒子的高度),就能夠看到正確的現象:

總結:

若是一個元素要浮動,那麼它的祖先元素必定要有高度。

有高度的盒子,才能關住浮動。(記住這句過來人的經驗之語)

只要浮動在一個有高度的盒子中,那麼這個浮動就不會影響後面的浮動元素。因此就是清除浮動帶來的影響了。

方法2:clear:both;

網頁製做中,高度height其實不多出現。爲何?由於能被內容撐高!也就是說,剛剛咱們講解的方法1,工做中用得不多。

那麼,能不能不寫height,也把浮動清除了呢?也讓浮動之間,互不影響呢?

這個時候,咱們可使用clear:both;這個屬性。以下:

clear:both;

clear就是清除,both指的是左浮動、右浮動都要清除。意思就是:清除別人對個人影響。

這種方法有一個很是大的、致命的問題,它所在的標籤,margin屬性失效了。讀者能夠試試看。

margin失效的本質緣由是:上圖中的box1和box2,高度爲零。

方法3:隔牆法

上面這個例子中,爲了防止第二個div貼靠到第二個div,咱們能夠在這兩個div中間用一個新的div隔開,而後給這個新的div設置clear: both;屬性。既然這個新的div沒法設置margin屬性,咱們能夠給它設置height,以達到margin的效果(曲線救國)。這即是隔牆法。

咱們看看例子效果就知道了:

上圖這個例子就是隔牆法。

內牆法:

近些年,有演化出了「內牆法」:

上面這個圖很是重要,看成內牆法的公式,先記下來。

爲了講內牆法,咱們先記住一句重要的話:一個父親是不能被浮動的兒子撐出高度的。舉例以下:

(1)咱們在一個div裏放一個有寬高的p,效果以下:(很簡單)

(2)可若是在此基礎之上,給p設置浮動,卻發現父親div沒有高度了:

(3)此時,我麼能夠在div的裏面放一個div(做爲內牆),就可讓父親div恢復高度:

因而,咱們採用內牆法解決前言中的問題:

與外牆法相比,內牆法的優點(本質區別)在於:內牆法能夠給它所在的家撐出寬度(讓box1有高)。即:box1的高度能夠自適應內容。

而外牆法,雖然一道牆能夠把兩個div隔開,可是這兩個div沒有高,也就是說,沒法wrap_content。

清除浮動方法4:overflow:hidden;

咱們可使用以下屬性:

overflow:hidden;

overflow即「溢出」, hidden即「隱藏」。這個屬性的意思是「溢出隱藏」。顧名思義:全部溢出邊框的內容,都要隱藏掉。以下:

上圖顯示,overflow:hidden;的本意是清除溢出到盒子外面的文字。可是,前端開發工程師發現了,它能作偏方。以下:

一個父親不能被本身浮動的兒子,撐出高度。可是,只要給父親加上overflow:hidden; 那麼,父親就能被兒子撐出高了。這是一個偏方。

舉個例子:

那麼對於前言中的例子,咱們一樣可使用這一屬性:

浮動清除的總結

咱們在上一段講了四種清除浮動的方法,本段來進行一個總結。

浮動的元素,只能被有高度的盒子關住。 也就是說,若是盒子內部有浮動,這個盒子有高,那麼妥妥的,浮動不會互相影響。

一、加高法

工做上,咱們絕對不會給全部的盒子加高度,這是由於麻煩,而且不能適應頁面的快速變化。

<div>     //設置height
    <p></p>
    <p></p>
    <p></p>
</div>

<div>    //設置height
    <p></p>
    <p></p>
    <p></p>
</div>

二、clear:both;

最簡單的清除浮動的方法,就是給盒子增長clear:both;表示本身的內部元素,不受其餘盒子的影響。

<div>
    <p></p>
    <p></p>
    <p></p>
</div>

<div>   //clear:both;
    <p></p>
    <p></p>
    <p></p>
</div>

浮動確實被清除了,不會互相影響了。可是有一個問題,就是margin失效。兩個div之間,沒有任何的間隙了。

三、隔牆法

在兩部分浮動元素中間,建一個牆。隔開兩部分浮動,讓後面的浮動元素,不去追前面的浮動元素。
牆用本身的身體當作了間隙。

<div>
    <p></p>
    <p></p>
    <p></p>
</div>

<div class="cl h10"></div>

<div>
    <p></p>
    <p></p>
    <p></p>
</div>

咱們發現,隔牆法好用,可是第一個div,仍是沒有高度。若是咱們如今想讓第一個div,自動根據本身的兒子撐出高度,咱們就要想一些「小伎倆」。

內牆法:

<div>
    <p></p>
    <p></p>
    <p></p>
    <div class="cl h10"></div>
</div>

<div>
    <p></p>
    <p></p>
    <p></p>
</div>

內牆法的優勢就是,不只僅可以讓後部分的p不去追前部分的p了,而且能把第一個div撐出高度。這樣,這個div的背景、邊框就可以根據p的高度來撐開了。

四、overflow:hidden;

這個屬性的本意,就是將全部溢出盒子的內容,隱藏掉。可是,咱們發現這個東西可以用於浮動的清除。
咱們知道,一個父親,不能被本身浮動的兒子撐出高度,可是,若是這個父親加上了overflow:hidden;那麼這個父親就可以被浮動的兒子撐出高度了。這個現象,不能解釋,就是瀏覽器的偏方。
而且,overflow:hidden;可以讓margin生效。

清除浮動的例子:

咱們如今舉個例子,要求實現下圖中無序列表部分的效果:

對比一下咱們講的四種清除浮動的方法。若是用外牆法,ul中不能插入div標籤,由於ul中只能插入li,若是插入li的牆,會浪費語義。若是用內牆法,不美觀。綜合對比,仍是用第四種方法來實現吧,這會讓標籤顯得極其乾淨整潔:

上方代碼中,若是沒有加overflow:hidden;,那麼第二行的li會緊跟着第一行li的後面。

瀏覽器的兼容性問題

講一下上述知識點涉及到的瀏覽器兼容問題。

兼容性1(微型盒子)

兼容性的第一條:IE6不支持小於12px的盒子,任何小於12px的盒子,在IE6中看都大。即:IE 6不支持微型盒子。

舉個例子。咱們設置一個height爲 5px 、寬度爲 200px的盒子,看下在IE 8和 IE 6中的顯示效果:

解決辦法很簡單,就是將盒子的字號大小,設置爲小於盒子的高,好比,若是盒子的高爲5px,那就把font-size設置爲0px(0px < 5px)。以下:

height: 5px;
_font-size: 0px;

咱們如今介紹一下瀏覽器hack。hack就是「黑客」,就是使用瀏覽器提供的後門,針對某一種瀏覽器作兼容。

IE6留了一個後門:只要給css屬性以前,加上下劃線,這個屬性就是IE6的專有屬性。

好比說,咱們給背景顏色這個屬性加上下劃線,就變成了_background-color: green;。效果以下:

因而乎,爲了解決微型盒子(即height小於12px)的問題,正確寫法:(注意不要忘記下劃線)

height: 10px;
_font-size:0;

兼容性2

兼容性的第二條:IE6不支持用overflow:hidden;來清除浮動。

解決辦法,以毒攻毒。追加一條:

_zoom:1;

完整寫法:

overflow: hidden;
_zoom:1;

實際上,_zoom:1;可以觸發瀏覽器hasLayout機制。這個機制,不要深究了,由於只有IE6有。咱們只須要讓IE6好用,具體的實現機制,能夠自行查閱。

須要強調的是,overflow:hidden;的本意,就是讓溢出盒子的border的內容隱藏,這個功能是IE6兼容的。不兼容的是overflow:hidden;清除浮動的時候。

總結:

咱們剛纔學習的兩個IE6的兼容問題,都是經過多寫一條hack來解決的,這個咱們稱爲伴生屬性,即兩個屬性,要寫一塊兒寫。

屬性1:

height:6px;
_font-size:0;

屬性2:

overflow:hidden;
_zoom:1;

margin相關

咱們來說一下浮動中和margin相關的知識。

margin塌陷

標準文檔流中,豎直方向的margin不疊加,以較大的爲準(水平方向的margin是能夠疊加的,即水平方向沒有塌陷現象)。以下圖所示:

若是不在標準流,好比盒子都浮動了,那麼兩個盒子之間是沒有塌陷現象的。

盒子居中margin:0 auto;

margin的值能夠爲auto,表示自動。當left、right兩個方向都是auto的時候,盒子居中了:

margin-left: auto;
margin-right: auto;

盒子居中的簡寫爲:

margin:0 auto;

對上方代碼的理解:上下的margin爲0,左右的margin都儘量的大,因而就居中了。

注意:

  • (1)使用margin:0 auto;的盒子,必須有width,有明確的width。(能夠這樣理解,若是沒有明確的witdh,那麼它的witdh就是霸佔整行,沒有意義)
  • (2)只有標準流的盒子,才能使用margin:0 auto;居中。也就是說,當一個盒子浮動了、絕對定位了、固定定位了,都不能使用margin:0 auto;
  • (3)margin:0 auto;是讓盒子居中,不是讓盒子裏的文本居中。文本的居中,要使用text-align:center;

對上面的第三條總結一下:

margin:0 auto;    //讓這個div本身在大容器中居中。
text-align: center;  //讓這個div內部的文本居中。

順便普及一下知識,text-align還有:

text-align:left;     //沒啥用,由於默認居左
text-align:right;    //文本居右

善於使用父親的padding,而不是兒子的margin

咱們來看一個奇怪的現象。如今有下面這樣一個結構:(div中放一個p)

<div>
        <p></p>
    </div>

上面的結構中,咱們嘗試經過給兒子p一個margin-top:50px;的屬性,讓其與父親保持30px的上邊距。結果卻看到了下面的奇怪的現象:

此時咱們給父親div加一個border屬性,就正常了:

若是父親沒有border,那麼兒子的margin實際上踹的是「流」,踹的是這「行」。因此,父親總體也掉下來了。

margin這個屬性,本質上描述的是兄弟和兄弟之間的距離; 最好不要用這個marign表達父子之間的距離。

因此,若是要表達父子之間的距離,咱們必定要善於使用父親的padding,而不是兒子的margin。

關於margin的IE6兼容問題

IE6的雙倍margin的bug:

當出現連續浮動的元素,攜帶與浮動方向相同的margin時,隊首的元素,會雙倍marign。

<ul>
        <li></li>
        <li></li>
        <li></li>
    </ul>

解決方案:

(1)使浮動的方向和margin的方向,相反。

因此,你就會發現,咱們特別喜歡,浮動的方向和margin的方向相反。而且,前端開發工程師,把這個當作習慣了。

float: left;
    margin-right: 40px;

(2)使用hack:(不必,別慣着這個IE6)

單獨給隊首的元素,寫一個一半的margin:

<li class="no1"></li>
ul li.no1{
    _margin-left:20px;
}

PS:雙倍margin的問題,面試常常問哦。

IE6的3px bug

解決辦法:不用管,由於根本就不容許用兒子踹父親(即描述父子之間的距離,請用padding,而不是margin)。因此,若是你出現了3px bug,說明你的代碼不標準。

IE6,千萬不要跟他死坑、較勁,它不配。 格調要高,咱們講IE6的兼容性問題,就是爲了增長面試的成功率,不是爲了成爲IE6的專家。

個人公衆號

想學習代碼以外的軟技能?不妨關注個人微信公衆號:生命團隊(id:vitateam)。

掃一掃,你將發現另外一個全新的世界,而這將是一場美麗的意外:

相關文章
相關標籤/搜索