標籤:

在 CSS 中,用 float 和 position 的區別是什麼?


在已有的回答中,我最贊同田樂。這裡稍作補充。

在絕大多數Web開發者的語境中,「布局」這個術語和「排版」是有差異的。「布局」偏向於指宏觀的GUI區域劃分,比如雙欄布局或三欄布局等。從這一點出發,float其實本不是一項用於「布局」的屬性。float對應的其實是傳統印刷排版中圖文混排中的環繞。這其實可以理解,因為CSS的模型和術語脫胎於傳統排版,故而與計算機GUI技術通常基於組件的模型相差甚遠。除了float之外,另一個例子是CSS中上下margin的collapse,顯然這是為了滿足段落排版的需求。所以像float、margin collapse等,在典型的GUI技術中是沒有的。還有,CSS box model中,width/height不算入padding和border,許多開發者對這點很不適應,這實際上是GUI的控制項思維與CSS排版思維的衝突。這個衝突在瀏覽器技術實現上的遺迹就是IE臭名昭著的「hasLayout」。元素「has layout」的真實意思是這樣的元素直接對應一個控制項。也正是由於IE很naive的在實現中直接結合了這兩種矛盾的模型,從而導致了無數的布局bug。

言歸正傳,CSS1時代的網頁還很簡陋,但是隨著萬維網的迅猛發展,Web界面也迅速進化,當初簡單的如同書頁般的通欄式網頁迅速絕跡,frameset由於天生存在的一堆問題也很快退出主流,這時CSS在GUI布局方面就顯出了缺陷,開發者被迫使用各種trick。比如歷史悠久的table布局。後來table布局被鄙視,開發者逐漸轉向了float布局。

要說float布局之所以流行,IE「功」不可沒。在IE中,has layout的元素是不會環繞float元素的(因為has layout的元素自己是一個控制項,所以總是保持一個矩形區域)。這本來是一個bug,但是其效果卻正好符合常見的雙欄布局的需要。另外IE下float元素會自動撐開其父級container元素(當然前提是container元素也是has layout的),這其實也是bug,但是也恰好符合模塊布局的需求。後來所謂inline-block布局其實正是這些bug的合理化。

站在今天回望過去十多年的CSS實踐,我們可以發現,無論float布局還是後來的inline-block布局,其實都是trick。所謂trick,就是將一些特性挪作他用,以很曲折的方式實現出想要的效果。CSS作為樣式語言,其可維護性的最終來源,就是代碼能清晰的表達出設計意圖。而CSS trick當然不能很好的滿足這一點。

那麼如何才能真正用CSS來表達布局?如田樂所說,這有賴於「CSS3的進化」。如multiple column、flex box、grid layout等。其中直接對應目前float布局/inline-block布局所要達到效果的,是flex box。當然,考慮到兼容性問題(IE9仍不支持flex box模塊,IE10才支持),我們可能很長時間內還是會繼續使用float布局,不過必須始終牢記這是trick,是workaround。如有可能,最好引入SCSS/LESS之類的CSS框架來對此種布局trick做進一步抽象和解耦。

再說position布局。position其實比float要更接近「布局」屬性。但是position的問題是,所謂布局是設定各區域(元素)的關聯和約束,而定位只是設定單一元素的位置大小。要實現一個布局,要對多個定位元素中手動設定相關的參數(如左欄width:200px,右欄left:200px),相當於人為的把大小和位置參數計算出來。這違背了DRY原則,也無法真正實現關聯約束。(如左欄設了max/min-width之後,最終實際width未必是200px,此時右欄怎麼設left值?又如一個水平固定width、垂直自適應height的絕對定位元素,我們如何從它的底部繼續排下一個元素?)除非我們引入JavaScript腳本來進行計算。因此運用position布局的限制條件相當多,通常只適合那些相對孤立的部件(如頁頭頁腳)或較為簡單且各區域大小位置固定的布局。至於說以JavaScript實現的布局管理器,是將position作為實現布局的底層技術,已經算不得CSS了(因為你也不寫CSS)。


呃,其實這個命題有誤,只有position才是定位,float不能說是定位,不過你可以說這兩種布局方式有什麼不同。

float和position這兩者並沒有孰好孰不好的問題,兩者按需使用,各得所需的效果。

float從字面上的意思就是浮動,這種在印刷排版之類中可能解釋的更加貼切。float能讓元素從文檔流中抽出,它並不佔文檔流的空間,典型的就是圖文混排中文字環繞圖片的效果了。並且float這也是目前使用最多的網頁布局方式。不過需要注意的是清除浮動是你可能需要注意的地方。並且如果你要考慮到古老的IE6之類的還會有一些bug諸如雙邊距等等問題。

而position顧名思義就是定位。他有以下這幾種屬性:static(默認),relative(相對定位),absolute(絕對定位)和fixed(固定定位)。其中static和relative會佔據文檔流空間,他們並不是脫離文檔的。absolute和fixed是脫離文檔流的,不會佔據文檔流空間。

比較可以發現,float和position最大的區別其實是是否佔據文檔流空間的問題。雖然position有absolute和fixed這兩個同樣不會佔據文檔流的屬性,但是這兩個並不適合被用來給整個網頁做布局。為什麼?因為這樣你就得為頁面上的每一個元素設置一個xy坐標來定位。

float布局就顯得靈活多了。但是一些特殊的地方搭配relative和absolute布局可以實現更好的效果。因為absolute是基於父級元素的定位,當父級元素是relative的時候,absolute的元素就會是基於它的定位了。比如你可以讓一個按鈕始終顯示在一個元素的右下角。

如果說到性能問題reflow問題,將元素的position設置為absolute和fixed可以使元素從DOM樹結構中脫離出來獨立的存在,而瀏覽器在需要渲染時只需要渲染該元素以及位於該元素下方的元素,從而在某種程度上縮短瀏覽器渲染時間。所以如果是製作js動畫等,用absolute或者fixed定位會更好。

說得不好的地方請大家補充。總結一句就是不推薦用position來布局整個頁面的大框架,而推薦用float或者文檔流的默認方式。


我補充一下float的問題。我們常說的文檔流其實是指默認文檔流。基本顯示模型block和inline分別是塊狀換行和連續多行模型,前者可以設定尺寸,後者不可以設定尺寸(根據內容決定尺寸和折行)。

不過我們總是遇到固定尺寸,或者固定部分尺寸且不折行的場景,這個時候我們馬上會想到使用float來做布局,因為float會觸發shrink to fit特性,實現根據內容決定尺寸,float還不會產生折行,我們通過clear來手工模擬折行。這個現狀我覺得主要是因為對inline-block的兼容性顧忌產生的,在IE6的時候它沒有被廣泛支持。使用position實現這樣的布局需要配合javascript修正,在某些場景它比float強,因為float模擬的流動布局不是多行連續布局,一些浮動元素經常因為意外的尺寸改變被卡在我們不希望它出現的位置。所以我們可以看到像pinterest這樣的網站使用了javascript配合absolute position的方式,講布局引擎的任務完全交給javascript來實現。從表現與行為分離的角度它不太合理,但是從結果上來說它很讓人滿意。

但是,我寫這段的意思是說,很多時候我們希望控制的布局流問題不需要float和position實現,而應該通過顯示模型定義來解決。比如現在的column layout、flex box等等,都是在這個角度解決我們遇到的問題,它們應該才是正解。而我們犯這個錯誤的最初原因也許就是對像inline-block這樣的顯示模型的不信任開始的。

希望CSS3的進化能夠讓我們重建這樣的信任。

UPDATE: 我忘記說的就是如果你做移動的Web開發,那麼你就知道為啥float很少在布局上使用。Android和iOS裡面的flex box已經非常穩定了,很低版本(Android 1.6,iOS 3)就已經很好支持了,用這些布局模型在窄小且多樣的手機屏幕上面相當可靠,而float在這些情況下則問題層出不窮。所以我現在相信mobile first,也相信移動設備的Web能夠更好的推廣CSS3的眾多新特性的採用。比如新的CSS3 background and box module在移動設備裡面幾乎是必備的,因為background-size是retina display必用的,而border-image則是解決複雜的按鈕和面板的最佳解決方案。如果你做Mobile Web,那麼你就會愛上CSS3新特性,也會享受它帶來的標準化的世界的好處。

UPDATE: THE FUTURE OF CSS LAYOUT PRESENTATION AT FUTURE OF WEB DESIGN CONFERENCE http://zomigi.com/blog/future-css-layout-fowd/


其實沒可比性。position不是用來做布局。float是傳統css布局手段, 其實可以和非float布局方式比較一下,像用inline block布局。典型的應用就是yui3 grids : http://yui.yahooapis.com/3.3.0/build/cssgrids/grids.css


一般先考慮 float,然後position

話說兩個沒有什麼衝突的吧


要引入bfc的概念,bfc具體是啥請百度嗷嗷嗷~

一個html文檔的正常文檔流應該是所有塊級元素從上往下依次排列,所有行內元素沿著行間排列。

而bfc則是打破了這種排列,float和position就是bfc的兩種用例,當float的屬性值不為none的時候,就會觸發bfc,它可以讓塊元素脫離文檔流原本的排列順序也沿著行間排列,這就是浮動。

position的屬性值不為默認的static的時候也會觸發元素的bfc,使得元素脫離原文檔流,擁有定位的功能。

這裡說下所謂脫離文檔流就好比是說該元素突然在正常的文檔流里消失了。因此會出現如果母元素不清楚浮動,母元素就包不住浮動子元素這樣的情況。


其實position和float完全是兩個概念。這方面李錦講的很詳細。

不過position相對於float更為靈活,是真正意義上的定位,尤其是absolute和fixed兩個屬性可以很簡單的設置xy定義到你想定義到的位置(不過需要搭配relative等相關配置),float不能做到精確定位。


兩個屬性在布局而言可比性不是太強,可以看看yahoo出的Pure css框架,完全的放棄float的布局理念,採用的是inline block,值得學習參考下。


共同點:對內聯元素設置float或absolute屬性,可以讓元素脫離文檔流(塊級元素也可以),並且可以設置其寬高。

不同點:

float仍會佔據其位置,position會覆蓋文檔流中的其他元素。


基礎的知識和原理,李錦已經說很好了。但我不太同意「float布局就顯得靈活多了」的觀點,其實最靈活的是position,可以隨心所欲,並且兼容性更好。當然,具體情況具體分析,絕大多數靈活布局控制其實都需要float+position匹配的方式來實現,區別在於主次。一段時間內,我很討厭float做主布局,浮動的邏輯不是那麼純粹。

好吧,隆重推薦一篇五年前研究的內容,看能否碰撞出新思路。如果我們把每個模塊抽象成為一個平面,從三維的角度來看,有了前後的關係,一個頁面就可以看做N個層的重疊,通過層之間的互相透視,二維上形成一個頁面。

三維角度設計頁面布局

http://blog.rexsong.com/?p=279


position 不佔用頁面空間 會有重疊問題

float 有兼容錯位問題

兩者結合使用時 position高度變長時,文檔中元素不會被撐下去,因為position不佔空間。

根據經驗:結構相對固定的區域用position, 剩下的都用float。


各有優勢,position是真正的定位,float只能算是布局吧。相對來說position的定位更精確,能實現很多特殊的效果。一些輕量級的布局定位推薦使用float,比如頁面框架的分欄式布局,某些精細的定位布局適用於position。

兩者之間沒有優劣,如果非要對比的話float相對來說IE6下BUG更多一些吧,不過position也有,而且float使用的時候一定要注意clear,這又會產生一個新的問題,如何clear。真對不同需求合理選擇,float+position配合使用有的時候會達到意想不到的效果


有時候float用的錯位但又實在沒精力去查就改用position吧,哈偷個懶。


position用作整個網頁的布局情況確實較少,不過禪意花園上面不少例子都用到了position,自己在實際工作中布局還是多用float。


現在開始應該用flexbox了


手機回答一下,

float最初是用來調節包圍文字的,記住這點。

position是用來調節文檔流中位置

具體可以去看慕課網關於浮動定位和絕對定位


布局的過程是這樣的

HTML解決:div,span,table=〉解決不了

CSS解決:先float,再position=〉解決不了

上js。。。。


蝸牛講的很詳細,個人認為還是要看具體的情況的,比如玉伯的雙飛翼布局就是二者結合的,比較方便實用!


一個絕對定位一個浮動


float的位置並不固定,只是一種浮的狀態。定位還得用position。


推薦閱讀:

html移動端頁面、圖片多少寬度最合適?
目前有哪些製作 Material Design 風格網頁的庫?
如何看待web開發前端框架QUICK UI?
CSS3 中存在哪些重要的概念?
如何判斷一個APP頁面是否是H5頁面?

TAG:前端開發 |