CSS魔法堂:说说Float那个被埋没的志向
前言
?定位系統中第一難理解就是Normal flow,而第二就非Float莫屬了,而Float難理解的原因有倆,1. 一開頭我們就用錯了;2. 它跟Normal flow靠得太近了。本文嘗試理清Float的特性和行為特征,若有紕漏望各位指正。
被埋沒的志向——文字環繞
?回憶一下我們一般什么時候會想用浮動呢?是多列布局還是多列布局呢:)?其實它向往的卻是這個
它想干的就是這個——文字環繞,而且CSS2中除了浮動外沒有其他屬性可實現上述的效果。
那到底如何理解它的實現原理呢?下面我們采取分步剖析的方式來深入探討吧!
切斷關聯看Float
'float'
Value: left | right | none | inherit
Initial: none
Applies to: all
Inherited: no
當設置float:left后,元素對應的margin left edge會盡可能向所屬的containing block的左邊框靠近,若同一行中存在位于左側的元素設置了float:left,則即會盡可能向該兄弟元素的margin right edge靠近.
(由于float:left突出不了效果,因此采用float:right作例子。其中藍色區域就是containing block范圍,綠和紅色塊采用向右浮動)
當設置浮動后,display:inline的實際值將被改寫為display:block,因此不要再為display:inline;height:100px;line-height:0;float:left導致盒子content height為100px感到驚訝了。也不要為即使剩余空間不足以存放整個display:inline;float:left盒子,導致整個盒子下移到下一行排版而驚訝了.(若為Normal flow則會根據white-spacing、word-wrap和word-break決定盒子內部分內容換行,而不是整個盒子換行)簡單來說并不是float:left讓盒子具有不為五斗米折腰的氣質,而是display:block的功勞,又由于浮動的盒子會以水平方向排版,因此我們可以以display:inline-block來理解浮動定位的水平排版和換行行為。
當設置浮動后,雖然display的實際值為block但就width:auto而言,我認為display更像是采用inline-block,寬度由子元素決定。這就是包裹性了!
(float:right同理,只是方向不同而已)
注意:在僅考慮浮動元素本身的前提下,float:left的效果與display:inline-block而父容器direction:ltr的效果是一樣的,不同的是浮動元素不納入父容器高度的計算當中
頭痛的開始——基于Normal flow看Float
?用割裂的方式理解float并不難,難就難在結合Normal flow看Float。下面我們一起來探討吧!警告,前方高能,前方高能!!
以Normal flow為基礎
?不管是Absolute positioning還是Float均以Normal flow作為定位基礎,也就是說先假設有一個虛擬盒子以Normal flow進行定位,然后在這個基礎上添加Float的特性并影響其他盒子的布局。而浮動定位對于盒子自身而言僅影響其在水平方向上的定位,因此對于inline-level box而言其垂直方向上的定位并沒有發生變化,而對于block-level box而言因Collapsing margins的失效有可能會引起垂直方向上的移動。
?值得注意的是,浮動定位的虛擬盒子實際上是不占空間的。因此才有后續的浮動閉合和清除浮動的事。
壓榨line box
文字環繞很明顯就是活生生地把文字向兩邊擠,為"大哥"留下個位置,而且小弟們不要走太遠,必須時刻擁護著大哥。那大哥是如何圈住小弟們的呢?那得借助外力——line box。文字是以字形(glyph)的形式渲染,和它同一行的inline-level boxes均位于同一個line box中。而line box可謂是夾在containing block和浮動盒子之間勉強生存。
?若line box的寬度不足以容納glyph和inline-level boxes時,會在下方產生N個新的line boxes并在必要時拆分inline-level boxes,然后將glyph和inline-level boxes分布到各行的line boxes當中。
腳踩block-level box
?相對line box,block-level box就顯得不屈不撓了。width:auto時其寬度始終保持占滿containing block寬度的態度。但位于同一個stacking context中的浮動定位的盒子雖然和常規流中的盒子擁有相同的z-index(都是auto),但浮動定位的盒子擁有額外的優先級,導致它總位于常規流中的盒子之上。(關于分層顯示的內容可參考《CSS魔法堂:你真的理解z-index嗎?》)
通過創建BFC翻身做主人
?同樣是盒子,為啥你就可以在我上面呢?你有Float罩著,我也找弄個新的BFC來跟你抗衡。我們知道通過float:left|right或position:absolute|fixed或display:inline-block|table-cell|table|table-caption或overflow:auto|scroll|hidden均可讓盒子產生新的BFC。而產生BFC的盒子間天生排斥彼此。(但可通過后天的努力position:relative讓他們又互有交集^_^)
那現在的問題是采用Normal flow定位模式的會產生新的BFC的盒子到底是緊跟在Float定位盒子的后面,還是另起一行呢?答案是兩者都有可能,具體看剩余的寬度是否足以容納該盒子。其實就是如同設置父容器產生BFC,而該盒子采用Float定位模式。不信,你看
是"浮動閉合"還是"清除浮動"?
?我想各位都看過各種版本的clearfix實現,而最簡單粗暴的方式就是添加一個<div style="clear:both"></div>來清除浮動。我還聽過另一個名稱——"浮動閉合",那到底兩者有什么區別呢?在作區分之前我們先要明確問題的本身。
對于height:auto的容器而言,我們希望它能恰好包裹著所有子元素,但不幸的是采用浮動定位模式的子元素將不納入父容器的高度計算當中,那就會出現子元素戳穿父容器的風險。
從之前的內容我們了解到文字和inline-level boxes會環繞Float定位的盒子,而block-level box則被它踩在腳下。但現在希望后續盒子不再與Float定位的盒子有任何瓜葛。
面對這兩種需求,我們分別得出"浮動閉合"和"清除浮動"兩套方案。
浮動閉合
?就是讓height:auto的父容器包裹所有子元素,包括Float定位的子元素。方式很簡單,就是好讓父容器產生BFC。
清除浮動
?就是為浮動影響的范圍劃邊界。方式也很簡單,就是以一個clear:left|right|both的盒子作為邊界即可,其實就是引入空隙(clearance)。
首先clear屬性僅對block-level box有效,clear:left表示盒子的margin-left-edge不與浮動盒子接觸,而clear:right表示盒子的margin-right-edage不與浮動盒子接觸,clear:both自然是左右兩條margin-edge均不與浮動盒子接觸啦。有點虛,直接看療效吧!
?簡單地說就是float:left用clear:left來清除,float:right用clear:right來清除。而我們會發現一個怪異的現象,那就是設置clear:left|right|both的盒子的border top edge緊接著Float定位盒子的margin bottom edge,其實這是clearance來作祟。當設置clear:left|right|both的盒子A的border top edge與Float定位盒子B的margin box重疊時,那么就會在A的margin box和border top edge之間引入clearance,恰好讓A的的border top edge恰好不與B的margin bottom edge重疊。
<div style="margin-bottom:50px;background:#06F;height:100px;width:200px;float:left;"></div> <div style="margin-top:50px;border: solid 10px red;height:50px;width:200px;clear:left;"></div>.clearfix方案
?不管是浮動閉合也好,清除浮動也罷,我們的目的往往是兩者結合——Float定位的范圍與Normal flow定位的范圍分明,且采用Normal flow的父容器包裹所有子元素。那么可歸結為Normal flow的父容器包裹所有子元素。因此得到如下的HTML Markup
<div class="container clearfix"><!-- Float定位的范圍 --> </div> <!-- Normal flow定位的范圍 -->而具體的方案如下:
方案1
偽元素after表示創建一個display:block,innerText是content屬性值的元素作為該元素的最后一個子元素。注意content屬性值不能為空白,否則無法清除浮動。
方案2
注意:若頁面不是采用UTF-8編碼方式,那么\u200B表示的將不是零寬空白字符,從而導致方案2出問題。
方案3
由Nicolas Gallagher大濕提出的
這里有2個奇妙的地方:
浮動真的是定位模式的一員嗎?
?我們可以通過position屬性來設置Normal flow或Absoluting positioning,但卻要通過float屬性來設置Float,這讓我一度懷疑Float到底是不是定位模式的一員呢?
我是這樣理解的,Normal flow(包括Relative positioning)與Absoluting positioning是非我即你的關系,而Float和Relative positioning則是可疊加影響定位效果的關系,顯然必須另設一個屬性來設置更恰當。
期待更美的文字環繞
?有沒有發現通過float:left|right我們僅能得到要么圖片靠左要么圖片靠右的文字環繞效果,那如果我們希望得到如下的四周環繞的效果呢?
雖然已有案例是通過absolute positioning模擬出類似的效果,但布局排版固定導致無法適應大部分場景。如果有個float:both屬性值那該多好啊!另外大家是否覺得以下的環繞效果更有藝術范呢?
聽說通過CSS3的shapes特性可以實現四周環繞和上面非四四方方的環繞效果,日后好好研究研究!
2016/04/19補充-參考《CSS網站布局實錄-基于Web標準的網站設計指南(第2版)》的5.2.2 不規則文字環繞
總結
重構了幾次總算寫完了,想寫得清楚而又不哆嗦真心不易,繼續努力:)
尊重原創,轉載請注明來自:http://www.cnblogs.com/fsjohnhuang/p/5375753.html^_^肥子John
感謝
KB011: 浮動(Floats)
KB009: CSS 定位體系概述
CS001: 清理浮動的幾種方法以及對應規范說明
CSS float浮動的深入研究、詳解及拓展(一)
CSS float浮動的深入研究、詳解及拓展(二)
https://www.w3.org/TR/CSS2/visuren.html#flow-control
CS001: 清理浮動的幾種方法以及對應規范說明
Faking ‘float: center’ with Pseudo Elements
說說標準——CSS核心可視化格式模型(visual formatting model)之十:控制緊接浮動的排列-clear 特性
那些年我們一起清除過的浮動
如果您覺得本文的內容有趣就掃一下吧!捐贈互勉!
關注 - 85
粉絲 - 707 +加關注 3 0 ? 上一篇:CSS魔法堂:你一定誤解過的Normal flow
? 下一篇:CSS魔法堂:小結一下Box Model與Positioning Scheme
posted @ 2016-04-11 08:59 ^_^肥仔John 閱讀(867) 評論(1) 編輯 收藏 評論列表 #1樓34057062016/4/12 10:12:12 2016-04-12 10:12 站在楓中 好文! 支持(0)反對(0) 刷新評論刷新頁面返回頂部 注冊用戶登錄后才能發表評論,請 登錄 或 注冊,訪問網站首頁。 【推薦】超50萬VC++源碼: 大型工控、組態\仿真、建模CAD源碼2018!
【推薦】加入騰訊云自媒體扶持計劃,免費領取域名&服務器
最新IT新聞:
· 興趣降溫 安卓廠商無意模仿iPhone X推出3D識別
· 樂視云更名新樂視云聯:仍未獲云服務牌照
· 微軟搜索引擎Bing改進航班 電影和比賽結果查詢
· 彭博商業周刊:硅谷悄然掀起中國技術人員回國潮
· 英特爾宣布為2018平昌冬奧會提供VR賽事直播技術
? 更多新聞... 最新知識庫文章:
· 步入云計算
· 以操作系統的角度述說線程與進程
· 軟件測試轉型之路
· 門內門外看招聘
· 大道至簡,職場上做人做事做管理
? 更多知識庫文章...
公告
肥仔John@github作品:
iScheme—Scheme解釋器 本文轉自^_^肥仔John博客園博客,原文鏈接:http://www.cnblogs.com/fsjohnhuang/p/5375753.html,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的CSS魔法堂:说说Float那个被埋没的志向的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux内核链表深度分析【转】
- 下一篇: Qt编写OpenMP程序--HelloW