摘要:而在文檔流中,如果浮動元素和跟隨元素都是元素,它們兩在默認情況下都將占據一行。而由于浮動元素脫離了文檔流,如果父元素沒有指定高度或者其他元素撐起,也就出現了所謂的浮動元素的父元素高度塌陷。
為什么要寫《重塑你的CSS世界觀》系列文章
由于從工作到現在,我的主要工作都是寫JavaScript,幾乎沒怎么碰CSS,通常都是別人寫好界面,然后我來開發JavaScript邏輯代碼,這導致了嚴重的偏科,CSS弱得很,所以我決定要重新學習CSS,從打好CSS2的基礎開始。最近我開始在看一本關于CSS的書,這本書叫《CSS世界》,是張鑫旭這個CSS大神寫的,質量十分有保障。
這本書幾乎完全顛覆了我對于CSS的認知,幾乎等于重塑我的CSS世界觀。
子曰:學而不思則罔,思而不學則殆。
所以我決定把從這本書學習到的知識結合我看到的一些文檔來總結一下,以便以后復習使用,所以文章中的見解也有可能是錯的,不追求完全正確,而是希望能夠作為方法論來指導之后的CSS開發。如有錯誤,請諸君指正。
浮動的本質是什么?浮動的本質就是為了實現文字環繞效果 ——《CSS世界》第六章 流的破壞和保護
熟悉張鑫旭老師的人,應該在他的博客和一些視頻教程中都有聽到上面那句話,可能和我一樣,咋一看覺得懂,然后就不以為然就過去了,然后使用在float的時候還是錯誤百出。
撇開我們是前端開發者這個身份,讓我們作為一個普通用戶的角度來思考有哪些場景我們會用到文字環繞效果。相信很多人都是使用過Word這個軟件,在我們編輯圖文信息的時候,希望文字可以圍繞圖片來排列,也就是文字環繞,也就是從圖1變為圖2:
還是一樣,讓我們作為一個普通用戶來思考如何實現這一效果。為了方便,我在這里定義一些詞匯,將文本、段落稱之為跟隨內容,將圖片等需要被環繞的稱之為目標元素。
首先然后我們將這兩者簡化一下,分成兩個區塊,如圖:
而所謂的環繞,那就是把兩個區塊重疊在一起,目標元素懸浮于重疊區上面,而且重疊區不能有跟隨內容的內容,如圖:
所以要使得跟隨內容能夠環繞目標元素我們需要做到以下步驟:
使跟隨內容的頂部能夠上升到與目標元素頂部同一水平線上;
跟隨內容與目標元素的重疊區域不能有文字,不重疊區域按照原來的排版方式。
如何浮動? 脫離文檔流浮動最初是為了實現文字環繞效果,經過上面的討論我們意識到了需要讓浮動元素和跟隨元素的頂部上升到同一水平線上。而在文檔流中,如果浮動元素和跟隨元素都是Div元素,它們兩在默認情況下都將占據一行。所以我們要讓浮動元素脫離文檔流,這個時候跟隨元素才能根據文檔流的要求進行上移,從而達到視覺上的重疊效果。
而由于浮動元素脫離了文檔流,如果父元素沒有指定高度或者其他元素撐起,也就出現了所謂的浮動元素的父元素高度塌陷。
確定“包含塊”,在“當前行”進行浮動在進行原理分析前,讓我們先來看一段代碼,并想象它的渲染結果
我就是 一段文本浮動
此時,你腦海里想象的結果可能如下圖:
但實際運行效果卻是這樣的:
為什么會出現這種情況呢?讓我們從CSS的標準中找尋答案。W3C的CSS標準文檔關于浮動的描述中有這樣一段話:
A floated box is shifted to the left or right until its outer edge touches the containing block edge or the outer edge of another float
翻譯成中文就是:
一個浮動盒會向左或向右移動,直到其外邊界挨到包含塊邊界或者另一個浮動盒的外邊界。
OK,先撇開有多個浮動元素的情況,讓我們只考慮一個浮動元素的情況。注意到上述引用文本中的高亮詞沒有?包含塊(containing block),沒錯,之所以剛才我們對代碼運行的渲染效果的想象與實際瀏覽器運行的效果產生偏差,就是因為我們沒有意識到包含塊(containing block),或者識別錯了浮動元素的包含塊,而這個包含塊就是元素浮動的參考位置!
什么是包含塊?如果判斷一個元素的包含塊?在W3C的CSS標準文檔中關于包含塊的描述中有這樣一段話:
The position and size of an element"s box(es) are sometimes calculated relative to a certain rectangle,called the containing block of the element
翻譯成中文就是:
元素(生成的)盒的位置和大小有時是根據一個特定矩形計算的,叫做該元素的包含塊(containing block)
關于如何確定一個元素的包含塊,標準也給出了定義,由于英文的較長,閱讀起來比較吃力,在此我放一段中文的定義:
根元素所在的包含塊是一個被稱為初始包含塊的矩形。對于連續媒體,尺寸取自視口的尺寸,并且被固定在畫布開始的位置;對于分頁媒體就是頁區(page area)。初始包含塊的"direction"屬性與根元素的相同
對于其它元素,如果該元素的position是"relative"或者"static",包含塊由其最近的塊容器祖先盒的內容邊界(the content edge )形成
如果元素具有"position: fixed",包含塊由連續媒體的視口或者分頁媒體的頁區建立
如果元素具有"position: absolute",包含塊由最近的"position"為"absolute","relative"或者"fixed"的祖先建立,按照如下方式:
如果該祖先是一個行內元素,包含塊就是環繞著為該元素生成的第一個和最后一個行內盒的內邊距框的邊界框(bounding box)。在CSS 2.1中,如果該行內元素被跨行分割了,那么包含塊是未定義的
否則,包含塊由該祖先的內邊距邊界形成
??????????如果沒有這樣的祖先,包含塊就是初始包含塊
根據上面關于包含塊的定義,我們可以發現.float元素符合第2條,那么它的包容塊就是.box這個div的內容邊界,注意是內容邊界(the content edge ),而不是整個盒子,所以不包含padding、border、margin。
讓我們先來看一張關于盒模型圖:
W3C的CSS規范關于content edge的定義是:
The content edge surrounds the rectangle given by the width and height of the box, which often depend on the element"s rendered content The four content edges define the box"s content box.
翻譯成中文就是:
內容邊界環繞著盒的width和height指出的矩形,通常取決于元素的呈現(rendered)內容。4條內容邊界定義了盒的內容框(content box)
所以如果我們給.box類添加一個padding為10px的話,
.box { padding: 10px; }
浮動元素由于是貼著包容塊在浮動,而此時的包容塊僅僅是.box元素的內容區,不包含padding,所以就出現了,浮動元素與.box元素盒子之間的間距,效果如下:
OK,那如何通過只調整CSS的方式就達到我們一開始腦海里想象的渲染效果呢?答案就是讓.textspan元素成為.float元素的包含塊就行了,讓inline level element變成block level element,只需添加一句dispaly:inline-block或dispaly:block即可,這里我們還想保持.text元素的內聯性,所以我們添加:
.text { display:inline-block; }
此時的效果就是我們一開始想要的了
W3C的CSS標準規范中關于浮動的定義,一開頭就有這么一句:
A float is a box that is shifted to the left or right on the current line.
翻譯成中文就是:
浮動(盒)就是一個在當前行向左或向右移動的盒。
大家注意高亮詞當前行(the current line),一定要理解這個當前行,如果說包含塊(containing block)決定了浮動元素浮動的范圍的話,那這個當前行(the current line)就決定了在浮動范圍的哪個垂直位置進行浮動。
同樣,我們通過一個小場景來了解這個當前行的重要性。
想象一下,你接到了一個任務,要求實現一個三列布局,無論左右兩列的寬度怎么變化,中間列的寬度都要自適應,效果大概如下圖(為了突出效果,給三列都添加了背景顏色):
聰明的你可能已經想到了辦法,讓左右兩列浮動,中間列的左右margin值為auto,這樣就可以實現中間列自適應了。沒錯你覺得十分機智,然后按照設計圖的視覺你從左到右寫了三個div:
LeftMiddleRight
然而你運行代碼,你看到的效果卻是這樣的:
然后你的心情奔潰了:
遇事不慌,首先讓我們分析一下,浮動元素.right的包含塊是什么?沒錯,就是.container的內容邊界(content edge),所以雖然有點差錯,但好歹還在里面浮動著。
那接下來就是確定當前行(current line)了。
讓我們還原到最開始的時候的布局,去除.left和.right的浮動屬性,此時會有"三行"
首先我們讓.left浮動起來,在.container的內容邊界范圍中、“第一行”中向左浮動,由于其脫離了文檔流,.middle開始上移到“第一行”。
此時由于.middle的上移,.right元素也向上移動到了“第二行”,然后讓它浮動,此時.right的浮動范圍是.container的內容邊界范圍中,而浮動的當前行是“第二行”,所以就出現了.right元素掉下去浮動的效果了,因為它的“當前行”就是“第二行”,它其實沒有掉下去過!
那怎么樣才能解決,很簡單,讓.left和.right“同一行”不就好了。什么意思呢?
.left浮動的當前行是“第一行”,然后由于脫離了文檔流,后續的元素會往上移動一行,那我們讓.right緊跟在.left之后不就行了,.left浮動后,.right就會到“第一行”,此時浮動不就到了“第一行”的右邊了么。然后由于.right也脫離文檔流,.middle也上移到了“第一行”,具體代碼如下:
LeftRightMiddle
然后就是運行之后就是我們一開始想要的效果了:
看到這里相信你已經理解了許多,讓我們通過相關下面這段代碼的運行效果,來檢驗你是否真的理解了吧,提示:標題中的文字已經超出了.title的寬度了
我就是一個三級標題更多
如果你能腦補出下圖的效果,說明你已經懂了,如果還不能,請回到前文繼續閱讀。
讓我們用上面用過的套路來分析這一現象,首先確認.more元素的包含塊為.title元素的內容邊界,然后由于內容過長,寬度不夠,此時就變為了兩行顯示,而.more元素就在“第二行”,所以它的當前行就是“第二行”,添加浮動屬性之后,在.title元素的內容邊界范圍內的“第二行”向右浮動,就形成了我們看到的樣子。
如果希望無論標題內容無論多長,.more元素都要固定浮動在右邊,那么只需要將.more元素的代碼放置帶.title元素的最前方即可,也就是:
更多我就是一個三級標題
此時的效果就是我們想要的了
重疊區不允許渲染“內容”,行框盒子“卡位”,實現文字環繞這一部分其實是浮動的本質,卻經常被我們所遺忘,主要是因為這個文字環繞的效果主要影響的是浮動元素的跟隨元素。
由于這一部分規范中的定義比較晦澀,所以以下內容是我在閱讀《CSS世界》結合自身的理解來闡述的,如果你希望查看規范的原文,可以訪問這個鏈接。
首先由于浮動,浮動元素和跟隨元素出現了一定的重疊區,這一點大家都知道了,而要想內容環繞,則重疊區不能有內容,注意是內容,文本、svg、圖片等替換元素都被視為“內容”,基本都是inline或line-block的元素。
而無論是inline還是inline-block元素,都會產生“行框盒子”,在重疊區中不允許出現“內容”,也就可以轉化成重疊區的“行框盒子”需要“貼在”浮動元素浮動方向的反方向的側邊即可,就是說如果一個元素向左浮動,則跟隨元素在重疊區的“行框盒子”需要“貼在”浮動元素的右側邊,反之亦然。
讓我們看一段代碼:
我是匿名內聯盒子的文本 ,而我是內聯盒子的文本,如果文本很長,那就會出現balabalabala的效果。 充點字數哈兄弟。
我們用藍色背景高亮文本的第一行,就可以看得出來“行框盒子”卡浮動元素側邊的效果了,然后注意,重疊區是不能渲染“內容”,背景顏色不屬于“內容”,所以我們可以看到綠色背景色連重疊區也鋪滿。
這時候可能有大兄弟要問,那重疊區到底是浮動元素在上還是跟隨元素在上啊?答案就是:浮動元素在上。
讓我們加一段代碼驗證以下:
.float { background-color:yellow; }
效果如下:
總結當一個元素要進行浮動時,需要以下步驟:
脫離文檔流;
在“包含塊”范圍內及“當前行”上根據浮動方向進行浮動;
受浮動影響的元素在與浮動元素的重疊區中不允許渲染“內容”,受浮動影響的元素內的行框盒子進行“卡位”,實現文字環繞;
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/117455.html
摘要:而在文檔流中,如果浮動元素和跟隨元素都是元素,它們兩在默認情況下都將占據一行。而由于浮動元素脫離了文檔流,如果父元素沒有指定高度或者其他元素撐起,也就出現了所謂的浮動元素的父元素高度塌陷。 為什么要寫《重塑你的CSS世界觀》系列文章 由于從工作到現在,我的主要工作都是寫JavaScript,幾乎沒怎么碰CSS,通常都是別人寫好界面,然后我來開發JavaScript邏輯代碼,這導致了嚴重...
摘要:和可以看作是同父異母的兄弟關系。例子如下結果如下而父元素設置屬性的方式則是利用了的特性下面將會詳細講解結界全稱為,中文為塊級格式化上下文。 上一篇:《CSS世界》筆記三:內聯元素與對齊下一篇:《CSS世界》筆記五:CSS層疊規則及元素隱藏 寫在前面 原本博客名為浮動與定位,但是《CSS世界》第六章節的內容不僅有浮動定位,很大一部分篇幅都在講BFC和overflow。更吸引人的是,作者將...
摘要:正是因為沒有很好地了解負邊距才是導致各種奇怪的問題。不理解它負邊距不會在的設計窗口展示出效果。有兩種場景負邊距是很重要的。微調元素這是負外邊距最常也是最簡單的使用方式。 原文 The Definitive Guide to Using Negative Margins 自從1998年CSS2作為推薦以來,表格的使用漸漸退去,成為歷史。正因為此,從那以后CSS布局成為了優雅代碼的代名詞。...
摘要:概述在世界這本書中有一些黑魔法給列舉出來,在結合自己的理解。篇幅有點長,希望大家能夠堅持看完,一定會有收獲以下是摘自每章內一些重要的概念與技巧。 概述 在《css世界》這本書中有一些黑魔法給列舉出來,在結合自己的理解。篇幅有點長,希望大家能夠堅持看完,一定會有收獲!!!以下是摘自每章內一些重要的概念與技巧。其中有解決圖片間隙的問題、小圖標與文字居中問題等; ps: 特別是 line-h...
閱讀 1762·2021-11-24 09:39
閱讀 1551·2021-11-16 11:54
閱讀 3497·2021-11-11 16:55
閱讀 1655·2021-10-14 09:43
閱讀 1445·2019-08-30 15:55
閱讀 1232·2019-08-30 15:54
閱讀 3420·2019-08-30 15:53
閱讀 1337·2019-08-30 14:18