CSS中為什麼overflow:hidden能清除浮動(float)的影響?原理是什麼?

父塊沒有設置指定的高寬,當子塊設置為浮動後,原本包裹子塊的父塊的高度塌陷消失,這時給父塊設置overflow:hidden就能清楚浮動造成的影響,使父塊重新包裹子塊。

但這個有個本質問題,當父塊高度塌陷消失,這時給父塊設置overflow:hidden,按照這個屬性的本意,本應該是切掉超出父塊的內容,也就是應該將父塊之外的浮動的子塊切除隱藏。

但為什麼,這時沒有切除隱藏超出邊界的子塊,反而恰恰讓父塊重新有了高度包裹子塊,這難道不是和overflow:hidden的本意相背離了嗎?

為什麼效果里是沒有切除隱藏,反而是重新讓父塊生成高度包裹子塊以達到清楚浮動的影響。

請哪位高手能否從本質和根源上分析在這個效果里overflow:hidden背離其屬性本意的問題,從本質和根源上分析為什麼overflow:hidden背離其本意沒有切除隱藏反而產生了清楚浮動的影響。


瀉藥

不說BFC什麼的了

就「分析」下本意

overflow:hidden 的意思是超出的部分要裁切隱藏掉

那麼如果 float 的元素不佔普通流位置

普通流的包含塊要根據內容高度裁切隱藏

如果高度是默認值auto

那麼不計算其內浮動元素高度就裁切

就有可能會裁掉float

這是反布局常識的

所以如果沒有明確設定容器高情況下

它要計算內容全部高度才能確定在什麼位置hidden

浮動的高度就要被計算進去

順帶達成了清理浮動的目標

同理

overflow 非默認值

position 非默認值

float 非默認值

等都是遵循這個布局計算思路

隨便瞎扯


BFC 沒有什麼好說的,這只是機制,不解答題主的疑問。在 BFC 語境下,題主的問題其實就轉換為了為啥 overflow: hidden 就是 BFC。

要說一點歷史了。

實際上 CSS 1 是沒有 overflow 屬性的(float 屬性已經有了)。overflow(以及許多複雜的 layout 機制)是 CSS 2 加入的。而 CSS 2 以 bug 眾多,實現不一而著稱。在原始的 CSS 2 中,overflow: hidden 時 float 的行為其實語焉不詳。如果你看一下 CSS 2.1 的附錄C——變更/錯誤/澄清和後續修改,搜索一下 overflow 關鍵字,會看到幾十處相關修訂。

注意 CSS 2.1 實際上很多地方是對既有瀏覽器的實現結果進行倒推的機制合理化。雖然我沒有拿老瀏覽器來測試,不過推斷 overflow 的行為應該也有許多地方是這樣來的。

站在今天審視 CSS ,也許使用一個單獨的屬性來構建 BFC 也是一種可能性(這樣當未開啟 BFC 時,overflow: hidden 可以呈現你描述的效果),不過歷史選擇了一條類似 IE 之 hasLayout 屬性的道路——即由某些其他顯式的屬性觸發一個隱式的超級屬性,該超級屬性可以決定其他屬性的實際意義。

最終的結果就是你看到的,overflow 取值只要不是 visible ,就會開啟這個超級屬性(BFC),此超級屬性反過來決定了 height: auto 是如何計算的(參考 @貘吃饃香的答案)。從 BFC 的機制設計來看,把 float 元素納入尺寸計算(即所謂父塊包裹子塊)是合理的。

至於你想要的效果,未來 clip-path 屬性(CSS Masking Module Level 1)將可提供。


看了一些文章,說下我的理解,不足之處歡迎指正:

1.BFC 全稱是塊級排版上下文,用於對塊級元素排版,默認情況下只有根元素(body)一個塊級上下文,但是如果一個塊級元素 設置了float:left,overflow:hidden或position:absolute樣式,就會為這個塊級元素生成一個獨立的塊圾上下文,就像在window全局作用域內,聲明了一個function就會生成 一個獨立的作用域一樣,新開僻的BFC像是開僻了一個新的小宇宙,使這個塊圾元素內部的排版完全獨立隔絕。

2.獨立的塊級上下文可以包裹浮動流,全部浮動子元素也不會引起容器高度塌陷,也就是說包含塊會把浮動元素的高度也計算在內,所以不用清除浮動來撐起高度。


因為height: auto;的計算結果不是一定為0的。

正常父元素包含浮動子元素,父元素的高度確實為0。

但是父元素overflow:hidden;後,首先會計算height: auto;的真實高度,由於其觸發了BFC,需要包含子元素,所以高度不是0,而是子元素高度。

這時overflow:hidden;才起到隱藏作用,不過父元素高度足夠大,所以子元素沒有被隱藏。

總之,是先計算真實高度,再去隱藏。如果是先直接隱藏了,再去計算高度也就沒有意義了。


因為overflow.hidden會觸發BFC。 BFC的意思是,我這個元素裡面的子孫元素,不會影響外部元素的布局。

但浮動本身會造成行內寬度的壓縮,出現文字環繞效果。如此一來,浮動元素越寬,當然行內的可容納的文字數就越少,文字的行數就會增加,文檔流高度也就增加。這樣,就影響了其外部元素的布局。

所以從BFC的本意來說,必須給浮動元素撐出高度,使得後續的元素無法跟浮動元素共享同一水平位置,看上去就是 clear both 的效果了。


看一下css 2.1 specification 的說法

出自:9.4.1

Floats ,absolutely positioned elements,block containers (such as inline-block,table-cells,and table-captions)that are not block boxes,and block boxes with「overflow "other than 「visible "(except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

為了跟它本身的注釋區別我自己的注釋都用/* */代替。

大概翻譯就是:浮動元素、絕對定位元素,除了塊盒之外的塊容器(例如inline-blocks,table-cells,table-captions)/*注釋:塊容器元素、塊盒元素、塊級元素是三個不同的概念,這三個概念在9.2.1有詳細說明,不過這裡不影響理解,總之就是這三個元素*/,以及overflow屬性設為非「visible」之外值的塊盒元素/*一般就指display屬性為「block」的元素*/(除了這個屬性值已經傳播到視口的情況)會為它們的內容建立新的塊布局上下文。

怎麼理解?

每個視口會默認建立一個塊布局上下文。只考慮上面說的塊盒元素(DIV,Hx,P...注意不包括table元素,它有自己的內部布局機制),假設一個文檔所有的這些塊盒overflow屬性都是「visible ",那麼它們必定屬於一個塊布局上下文,也就是視口所產生的布局上下文,而無論塊盒與塊盒之間的關係。但是一旦有一個塊盒設置了「visible」以外的值,新的塊布局上下文就產生了。它就像為它的內容開闢了新的擺放空間,這個擺放空間是相對獨立的。

再來看浮動元素,我們都知道浮動元素會從原來的文檔流中刪除,其實確切的講它是會從屬於它的布局上下文中刪除,如果父元素的overflow屬性為「visible」那麼它跟父元素屬於相同的布局上下文,在這個布局上下文里它是不佔文檔流的,所以父元素會坍塌,父元素後面的兄弟塊級元素會與之發生重疊。但是一旦設為「visible」以外的值,這時候父元素必須要為它的內容開闢一個新的獨立的擺放空間,所以它不能再坍塌,它必須雄起!

後話:這也解釋了為什麼把父元素同樣設為浮動元素父元素也不會坍塌。因為浮動和絕對定位元素也會建立新的塊布局上下文。

同樣可以說明一個有趣的現象:兩欄式布局中,左邊欄設為左浮動,右邊欄正常布局,但是裡面有個元素設置了clear:both屬性那麼這個元素的擺放會超出預期的跑到左邊欄下邊界的下方。

手機敲的,沒放案例,抱歉。


有一個很好的解決方案是Container Queries,而它的前身是Element Queries。他們的未來並不確定,但是其中的一些特性,可以通過Polyfills來實現。但話又說回來,使用Polyfill來實現一些特性,並不是長遠的方案,而且要通過Polyfill達到每一個特性,那也是一件非常艱巨的任務。

但是我們只能依賴於JavaScript或者說Container Queries?如果我們使用CSS就能解決Container Queries提供的一些特性,那是不是一個更值得可取的方案呢?接下來就來看幾個常見的例子。

長文本變得更短

在我們Web的實際使用中,常有這樣的一種效果。在有足夠的空間里顯示所有的文本內容出來,但在沒有足夠的空間里,通過text-overflow:ellipsis把要顯示的內容變短。但我們並不只是想把內容截取,比如我們想在有足夠的空間顯示一行文本,在不足夠的空間內顯示另一行文本,甚至是在更短的空間,只通過一個圖標來顯示。引用:web前端中文站 lisa33xiaoq.net

& & &Short text here is.& & &Some long text that could become shorter.& &


其實我不是來答題的.本來是要對這個問題進行提問的.知乎說我應該先搜索一下答案再提.然後我就來到了這.下面就是一段學習代碼.使用 ul 的 li 的浮雲顯示後 ul 就因為沒有高度而塌陷.此時對於 ul 後面的元素感覺就是 ul 不存在一樣.導致了後面 h1標籤直接顯示到了菜單右邊.而有 overflow:hidden 屬性後.ul 的背景屬性又有效了.而且後面的 h1標籤也作為塊元素正常的另起一行進行顯示了.我說不清楚這是為什麼.只是在這記錄此問題給大家討論一下.

&

&

&

&

&菜鳥教程(http://runoob.com)&

&

ul

{

/*不正常換行*/

list-style-type: none;

margin: 0;

padding: 0;

/*overflow: hidden;正常換行必須要的屬性*/

padding-top:1px;/*為了顯示方便.本來不會佔用空間*/

background-color:red;

}

li

{

float:left;

}

a:link,a:visited

{

font-weight:bold;

color:#FFFFFF;

background-color:#98bf21;

text-align:center;

padding:6px;

text-decoration:none;

text-transform:uppercase;

overflow:disable;

width:60px;

display:inline-block;

}

a:hover,a:active

{

background-color:#7A991A;

}

&

&

&

&

&&Home&&

&&News&&

&&3333&&

&&About&&

&

&h1標題&

&

&注意:&如果您只為 a 元素設置內邊距(而不設置 ul 元素),那麼鏈接會出現在 ul 元素之外。所以,我們為 ul 元素添加了 top 和 bottom 內邊距。 &

&

&


推薦閱讀:

webpack執行機制流程是怎麼樣的?
前端開發工作遇到瓶頸,不知何去何從?
如何搭建一個類似於 BrowserStack 的跨瀏覽器測試平台?
現在正在學習前端,是否應該寫技術博客和建github?應該在上面放些什麼東西?
WEB前端如何從工程上保證跨瀏覽器體驗?

TAG:前端開發 | CSS | CSS布局 |