深入理解css浮動
一、浮動介紹
歷史:
浮動屬性產生之初是為了實現“文字環繞”的效果,讓文字環繞圖片在網頁實現類似word中“圖文混排”。
定位方式:
浮動讓元素脫離正常流,向父容器的左邊或右邊移動直到碰到包含容器的邊【經測試碰到padding即停】或者碰到其他浮動元素。文本和行內元素將環繞浮動元素。
Note:
1、碰到容器的邊指的是容器的padding內邊。
舉例驗證:
<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>

2、浮動元素脫離正常流,意思是布局時后面元素當它不存在(文字還是當它存在,環繞其身邊),但仍然在dom樹上。
3、如果是在js中通過element.style設置元素浮動,需要用cssFloat,因為float是js中的一個關鍵字。【IE8及以下瀏覽器用styleFloat】
如下:
<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>
浮動影響:包裹性和破壞性,下面一一介紹。
二、包裹性
包裹性:這個詞是別人總結的,個人覺得總結的恰到好處。
包裹性指的是元素尺寸剛好容納內容。
具有包裹性的其他屬性:
- display:inline-block/table-cell/...
- position:absolute/fixed/sticky
- overflow:hidden/scroll
1、通過例子看看浮動的包裹性
舉例:
<style> .container{ border: 1px solid green; padding: 30px; background-color: green; background-clip: content-box;/*將背景裁剪到內容框,方便看浮動元素效果*/ } .fl{ float: left; } </style> <div class="container fl"> 內容 </div>

2、包裹性的原理
浮動之所以會產生包裹性這樣的效果是因為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>

可以利用浮動的包裹性來達到父容器自適應內部元素寬度。
三、破壞性
這里破壞性是指元素浮動后可能導致父元素高度塌陷。
其他破壞性的屬性:
- display:none
- position:absolute/fixed/sticky
浮動破壞性原理:
因為浮動元素被從文檔正常流中移除了,父元素當然還處在正常流中,所以父元素不能被浮動元素撐大。
四、清除浮動
1、clear屬性
clear屬性規定元素的哪一側不允許有其他浮動元素。
取值:
- left:元素左側不允許有浮動元素
- right:元素右側不允許有浮動元素
- both:元素左右兩側均不允許有浮動元素
- none:默認值,允許浮動元素出現在兩側
具體原理:在元素上外邊距之上增加清除空間,比如清除左浮動會讓元素的上外邊距剛好在左邊浮動元素的下外邊距之下。
清除浮動可兩大類方法
- 兄弟元素設置clear:both
- 父元素生成BFC(IE8+) 或haslayout(IE6/IE7)
下面具體分析。
2、方法一:兄弟元素設置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>

因為父元素生成的并不是浮動元素相鄰的兄弟元素,所以使用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; }
3、補充知識: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重疊
4、方法二:父元素生成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>

overflow: hidden;使得包含圖片的div生成BFC,所以里面內容元素與外面包含文字的div的margin不會重疊,如上圖。
兩種清除浮動方法區別:clear:both可以發生margin重疊,BFC隔離不會有margin重疊。
BFC缺點:
1、不能應用于所有場合,因為不可能所有元素都絕對定位或者不可能所有元素都浮動。
2、現代瀏覽器不認識zoom1。
5、清除浮動方法總結
每種清除浮動的方法都有弊端,權衡后推薦用法:
.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類只應該用在包含浮動元素的父元素上。【如果不懂這句話再把上文看一遍】
五、浮動布局
1、普通固定布局
通常用的浮動布局一般是:固定尺寸+浮動。
舉例:兩欄布局
<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>

問題:
容錯性差:容器尺寸變了,就得改代碼。
復用性不好:尺寸固定,模塊在另外尺寸容器中不能重用。
2、推薦布局
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>

不改變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>
效果同上。
大前端和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>

六、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.rzrgm.cn/starof/p/4608962.html有問題歡迎與我討論,共同進步。
如果覺得本文對您有幫助~可以微信支持一下:




浙公網安備 33010602011771號