深刻理解css浮動

1、浮動介紹

歷史:javascript

浮動屬性產生之初是爲了實現「文字環繞」的效果,讓文字環繞圖片在網頁實現相似word中「圖文混排」。css

定位方式:html

浮動讓元素脫離正常流,向父容器的左邊或右邊移動直到碰到包含容器的邊【經測試碰到padding即停】或者碰到其餘浮動元素。文本和行內元素將環繞浮動元素。前端

Note:java

一、碰到容器的邊指的是容器的padding內邊。css3

舉例驗證:chrome

<style>
.container{
    border: 1px solid green;
    padding: 30px;
    background-color: green;/*將背景裁剪到內容框,方便看浮動元素效果*/
    background-clip: content-box;
}
.fl{
    float: left;
}
</style>
<div class="container">
    文字會環繞在圖片周圍文字會環繞在圖片周圍文字會環繞在圖片周圍文字會環繞在圖片周圍
    <img class="fl" src="img/wb.jpg">
</div>
View Code

二、浮動元素脫離正常流,意思是佈局時後面元素當它不存在(文字仍是當它存在,環繞其身邊),但仍然在dom樹上瀏覽器

三、若是是在js中經過element.style設置元素浮動,須要用cssFloat,由於float是js中的一個關鍵字。【IE8及如下瀏覽器用styleFloat】app

以下:dom

<style>
#father{
    border:1px solid red;
}
#test{
  background-color: green;
  /*float: left;*/    
}
</style>
<div id="father">
<span id="test">span內容</span>
</div>
<script type="text/javascript">
    var oSpan=document.getElementById("test");
    oSpan.style["cssFloat" in oSpan.style? "cssFloat" : "styleFloat"]="left";
</script>

浮動影響:包裹性和破壞性,下面一一介紹。

2、包裹性

包裹性:這個詞是別人總結的,我的以爲總結的恰到好處。

包裹性指的是元素尺寸恰好容納內容。

具備包裹性的其餘屬性:

  • display:inline-block/table-cell/...
  • position:absolute/fixed/sticky
  • overflow:hidden/scroll

一、經過例子看看浮動的包裹性

舉例:

<style>
.container{
    border: 1px solid green;
    padding: 30px;
    background-color: green;
    background-clip: content-box;/*將背景裁剪到內容框,方便看浮動元素效果*/
}
.fl{
    float: left;
}
</style>
<div class="container fl">
內容
</div>
View Code

二、包裹性的原理

浮動之因此會產生包裹性這樣的效果是由於float屬性會改變元素display屬性最終的計算值

設置float前的display屬性——》設置浮動後的display屬性計算值

  • inline——》block
  • inline-block——》block
  • inline-table——》table
  • table-row——》block
  • table-row-group——》block
  • table-column——》block
  • table-column-group——》block
  • table-caption——》block
  • table-header-group——》block
  • table-footer-group——》blcok
  • flex——》flex
  • inline-flex——》inline-flex【inline-flex在chrome下測試,float後display:flex】
  • other——》unchanged

通過我測試只有inline-flex在chrome下float後display計算值變爲flex,其它都一致。感興趣的小夥伴可自行測試。

在此給你們提供一個很簡單的測試方法:好比就測試inline-flex,能夠選擇任意標籤,這裏我用span標籤,設置display屬性爲inline-flex,而後設置float:left。在chrome控制檯中style選項查看display屬性爲inline-flex,切換到computed選項查看display屬性爲flex,以下圖。測試其餘值可直接在控制檯編輯查看。

<style>
.test{
background-color: green;
display:inline-flex;
float: left;    
}
</style>
<span class="test">span內容</span>

 能夠利用浮動的包裹性來達到父容器自適應內部元素寬度。

3、破壞性

這裏破壞性是指元素浮動後可能致使父元素高度塌陷。

其餘破壞性的屬性:

  • display:none
  • position:absolute/fixed/sticky

浮動破壞性原理:

由於浮動元素被從文檔正常流中移除了,父元素固然還處在正常流中,因此父元素不能被浮動元素撐大。

4、清除浮動

一、clear屬性

clear屬性規定元素的哪一側不容許有其餘浮動元素。

取值:

  • left:元素左側不容許有浮動元素
  • right:元素右側不容許有浮動元素
  • both:元素左右兩側均不容許有浮動元素
  • none:默認值,容許浮動元素出如今兩側

 具體原理:在元素上外邊距之上增長清除空間,好比清除左浮動會讓元素的上外邊距恰好在左邊浮動元素的下外邊距之下。

 清除浮動可兩大類方法

  • 兄弟元素設置clear:both
  • 父元素生成BFC(IE8+) 或haslayout(IE6/IE7)

下面具體分析。

二、方法一:兄弟元素設置clear:both

clear:both方法也有下面幾種。

a、html層面經常使用方法

  • 在空 div 元素設置clear : both
  • br 標籤的 clear 屬性  <br style="clear:both">

舉例:

<style>
.wrap{
    background-color: green;
}
.fl{
    float: left;
}
</style>
<div class="wrap">
<img class="fl" src="img/wb.jpg" />
<div style=" clear:both;margin-bottom:50px;">兄弟元素設置clear:both</div>
</div>
<p style="margin-top: 50px;">兄弟元素設置clear:both來清除浮動會有margin重疊現象</p>

使用這種方法清除浮動,須要注意一點,就是margin重疊,由於清除浮動的元素和除浮動元素以外其餘元素仍是處於同一個BFC。

代碼層面的問題:

  • 用標籤來實現樣式效果,不符合結構表現分離原則。標籤複用變難。
  • 標籤沒有任何語義
  • 這樣寫代碼不專業
  • 未來有其餘清除浮動的方法,你必須回頭刪掉因此分散在html頁面中的<br>標籤

b、父元素添加 after 僞元素

由於上面方法的種種弊端,更推薦使用這種父元素添加after僞元素清除浮動的方法。

上面方法是在html層面寫的代碼,而after僞元素是在css層面寫的代碼,雖然代碼都很少,但站在結構和表現分離的角度看兩種方式仍是有差的。

代碼以下:after在父元素底部生成一個具備clear:both 聲明的僞元素來清除浮動。

.clearfix::before,
.clearfix::after{
    content: ".";
    display: block;
    height: 0;
    overflow: hidden;
}
.clearfix:after{
    clear: both;
}
.clearfix {
    zoom: 1; /* IE < 8 */
}

這種方法原理:

經過父元素的::after僞元素來生成浮動元素的兄弟元素,而後兄弟元素使用clear:both方法。

知道這點很重要,舉個反例子來講明一下:

<style>
.wrap{
    background-color: green;
}
.fl{
    float: left;
}
.clearfix::before,
.clearfix::after{
    content: ".";
    display: block;
    height: 0;
    overflow: hidden;
}
.clearfix:after{
    clear: both;
}
</style>
<div class="wrap clearfix">
<img class="fl" src="img/wb.jpg" />
<div >
    父元素的::after僞元素並非浮動元素【在這裏是圖片】的相鄰的兄弟元素,就達不到清除浮動的效果父元素的::after僞元素並非浮動元素【在這裏是圖片】的相鄰的兄弟元素,就達不到清除浮動的效果父元素的::after僞元素並非浮動元素【在這裏是圖片】的相鄰的兄弟元素,就達不到清除浮動的效果
</div>
</div>
View Code

由於父元素生成的並非浮動元素相鄰的兄弟元素,因此使用clear:both無效,使用時必須注意。

c、一個更簡潔的版本

支持瀏覽器: Firefox 3.5+, Safari 4+, Chrome, Opera 9+, IE 6+

/**
 * For modern browsers
 * 1. The space content is one way to avoid an Opera bug when the
 *    contenteditable attribute is included anywhere else in the document.
 *    Otherwise it causes space to appear at the top and bottom of elements
 *    that are clearfixed.
 * 2. The use of `table` rather than `block` is only necessary if using
 *    `:before` to contain the top-margins of child elements.
 */
.cf:before,
.cf:after {
    content: " ";
    display: table; 
}
.cf:after {
    clear: both;
}
/* IE < 8 */
/**
 * For IE 6/7 only
 * Include this rule to trigger hasLayout and contain floats.
 */
.cf {
    *zoom: 1;
}

瞭解更多可參考micro-clearfix-hack

 zoom是爲了兼容IE6,7;:before是爲了阻止margin重疊,若是隻清除浮動,可用:

.container:after {
  content:"";
  display:table;
  clear:both;
}

三、補充知識:BFC

BFC:塊級格式化上下文【在css3中叫Flow Root】是一個獨立佈局環境,相鄰盒子margin垂直方向會重疊。

什麼樣的元素會爲其內容生成一個BFC呢?

  • 浮動元素,即float:left|right
  • 絕對定位元素,即position:absolute|fixed
  • 塊容器【block containers】(好比inline-blocks,table-cells和table-captions),這些塊容器有個特徵就是它們不是塊級盒子【block boxes】。即display:table-cell|table-caption|inline-block
  • 設置了除visible外的overflow值的塊盒子【blok boxes】,即overflow:hidden|scroll|auto

BFC特性:

  • 建立了BFC的元素中,子浮動元素也會參與高度計算
  • 與浮動元素相鄰的、建立了BFC的元素,都不能與浮動元素相互覆蓋
  • 建立了BFC的元素不會與它們的子元素margin重疊

四、方法二:父元素生成BFC(IE8+) 或haslayout(IE6/IE7)

正是由於BFC特性中,建立了BFC的元素中,子浮動元素也會參與高度計算,因此可來清除浮動。

經常使用方法以下:

  • 浮動父元素(觸發 BFC)
  • overflow: hidden  (觸發 BFC) 
  • display: table或table-cells;(觸發 BFC,display:table  自己並不產生 BFC,而是由它產生匿名框,匿名框中包含 "display:table-cell" 的框會產 BFC)

舉例:父元素使用overflow:hidden生成一個BFC來清除浮動。

<style>
.wrap{
    background-color: green;
    overflow: hidden;
}
.fl{
    float: left;
}
</style>
<div class="wrap">
<img class="fl" src="img/wb.jpg" />
<div style=" margin-bottom:50px;">浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容浮動元素的兄弟元素的內容</div>
</div>
<p style="margin-top: 50px;">浮動元素父元素的兄弟元素內容</p>
View Code

overflow: hidden;使得包含圖片的div生成BFC,因此裏面內容元素與外面包含文字的div的margin不會重疊,如上圖。

兩種清除浮動方法區別:clear:both能夠發生margin重疊,BFC隔離不會有margin重疊。

 BFC缺點:

一、不能應用於全部場合,由於不可能全部元素都絕對定位或者不可能全部元素都浮動。

二、現代瀏覽器不認識zoom1。

五、清除浮動方法總結

每種清除浮動的方法都有弊端,權衡後推薦用法:

.clearfix:after{
content:"";
display:block;
height:0;
overflow:hidden;
clear:both;
}
/*IE6和IE7*/
.clearfix{
*zoom:1;
}

 或者用:

.clearfix:after{
content:"";
display:table;
clear:both;
}
/*IE6和IE7*/
.clearfix{
*zoom:1;
}

Note:

.clearfix類只應該用在包含浮動元素的父元素上。【若是不懂這句話再把上文看一遍】

5、浮動佈局

一、普通固定佈局

一般用的浮動佈局通常是:固定尺寸+浮動。

舉例:兩欄佈局

<style type="text/css">
  body{
    width: 600px;
  }
  .left{
    width: 150px; float: left; 
  }
.right { width: 450px; float: right; }
  </style>
<body>
  <div class="left">
    <img src="img/wb.jpg"/>
  </div>
  <div class="right">
    文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容
  </div>
</body>
View Code

問題:

容錯性差:容器尺寸變了,就得改代碼。

複用性很差:尺寸固定,模塊在另外尺寸容器中不能重用。

二、推薦佈局

a、左側尺寸固定右側自適應的流體佈局

舉例:在上面代碼基礎上修改樣式爲

<style type="text/css">
  .left{
    width: 150px; float: left; 
  }
  /*流體佈局*/
.right { margin-left: 150px;}
  </style>

重點是使用margin-left,且不要定寬。這樣好處是容器尺寸變化右側可自適應。

b、右側尺寸固定左側自適應的流體佈局

改變DOM位置的流體佈局寫法

寫代碼時順序爲先右後左,這樣就能夠設置右欄右浮動,左欄設置margin-right。

<style type="text/css">
.right{
float: right;
width: 150px;
}
.left{
margin-right: 150px;
}
  </style>
</head>
<body>
<div  class="right">
<img  src="img/wb.jpg">
</div>
<div class="left">
文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容
</div>
</body>
View Code

不改變DOM位置的流體佈局寫法【左右欄都左浮動】

寫代碼時順序不變,左右欄都浮動,經過margin調整位置。

<style type="text/css">
.wrap {
  width: 100%;
  float: left;
}
.left {
  margin-right: 150px;
}
.right {
  width: 150px;
  float: left;
  margin-left: -150px;
}
  </style>
<body>
<div class="wrap">
    <div class="left">
    文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容
    </div>
</div>
<div  class="right">
    <img  src="img/wb.jpg">
</div>
</body>
View Code

效果同上。

大前端w3cplus都是用的這種佈局方法(從20150706截止20170418)

c、兩欄都自適應的佈局

原理是左欄浮動,右欄生成BFC,根據BFC特性與浮動元素相鄰的、建立了BFC的元素,都不能與浮動元素相互覆蓋。

<style type="text/css">
.left {
  float: left;
}
.right{
   display: table-cell;
 }
  </style>
<body>
 <div class="left">
    <img src="img/wb.jpg"/>
  </div>
  <div class="right">
    文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容文本內容
  </div>
</body>
View Code

 

6、float佈局和inline-block佈局對比

浮動和inline-block都能讓元素排成一排,那麼應該如何抉擇?下面對比一下。

  • 文檔流:浮動元素脫離正常流,讓文字環繞。inline-block仍然在正常流中。
  • 水平位置:不能經過給父元素設置text-align:center讓浮動元素沒法水平居中【由於脫離文檔流】,而inline-block能夠。
  • 垂直對齊:浮動元素緊貼頂部,inline-block默認基線對齊,可經過vertical-align調整。
  • 空白:浮動忽略空白元素彼此緊靠,inline-block保留空白。

舉例:浮動佈局能夠去掉元素之間的空格,而inline-block會保留空格。

<style>
button {
    margin: 0;
    float: left;
}
p {
    clear: both;
}
</style>
</head>
<body>
    <button>按鈕1</button>
    <button>按鈕2</button>
    <button>按鈕3</button>
    <button>按鈕4</button>
</body>

分析:button默認display:inline-block;可見他們之間有空格的距離。加了float:left後各個button元素之間空格消失。

總結一下:處理文字環繞天然是用浮動,處理圖片列表垂直對齊或者橫向導航能夠選擇inline-block。

 

 

本文做者starof,因知識自己在變化,做者也在不斷學習成長,文章內容也不定時更新,爲避免誤導讀者,方便追根溯源,請諸位轉載註明出處:http://www.cnblogs.com/starof/p/4608962.html有問題歡迎與我討論,共同進步。

相關文章
相關標籤/搜索