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.1Floats ,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前端如何從工程上保證跨瀏覽器體驗?