SS的布局有太多種方式,元素的表現也有很多的形式。
像我們熟悉的那些:行內元素、塊元素、列表元素、表格元素、絕對定位、固定定位、浮動、彈性布局、網格布局等等等等。
一個元素的具體渲染可能會受到父子元素、兄弟元素的影響。
大多數情況我們都可以通過一些手段,來解決我們遇到的布局或表現問題。
比如給一個元素賦予了浮動,那么可以通過清除浮動來消除影響,再比如通過絕對定位來調整元素的位置,也可以通過padding或margin等避免其他元素被覆蓋。
但是也有那么一些情況,我們不太好處理,比如某一個元素希望相對于它的父級區域做固定定位,而不是基于整個頁面,能做到嗎?再比如給定一個盒容器,無論子元素怎么排序布局或者浮動,也不會影響其他相鄰盒子的渲染,該怎么做到?
其實不止這些,還有很多的實際場景讓我們很棘手,你是否在設計和實現方面做過平衡和妥協?
對于現在的瀏覽器來說,所支持的CSS功能不允許我們說:我不行,我做不到。
別的不說,今天要講的contain就能用來解決上面的問題,它能做的事情還有很多,基于自身天然的屬性,甚至能輕松提升你的性能!
contain表明該元素要獨立于頁面中的其他元素,該元素中的所有內容都被局限在一個獨立的區域,跟其他元素隔離開來,從而使得基于該元素的所有計算都是獨立的,被限制在該DOM子樹中,而不是整個頁面。這樣能夠讓頁面的性能提升。
該元素構成的容器,可以控制其產生的尺寸范圍、樣式作用域、布局方式、繪制區域。會生成新的包含區塊、新的層疊上下文、新的區塊格式化上下文。這些控制手段都對應著不同的局限屬性,在容器內對局限屬性的修改,不會影響容器外的部分,也就不會使得頁面經常重新渲染,尤其在動態修改頁面元素時會帶來更好的性能受益。
我們理解它的時候,不要把它想成是包含的意思,理解成它的作用,是對包含內容的一個局限,之后也會多次用到"局限"這個詞。
一、關鍵詞
通過關鍵詞,可以指定不同的局限屬性,從而產生不同的局限效果。
二、組合值
也就是上面2-6關鍵字的任意組合,跟順序無關,多個值之間用空格分隔開。跟個數也無關,可以設置任意的數量。不過要注意,size和inline-size同時只能設置一個,因為它倆是沖突的。
三、全局值
全局值的作用,可以參考我在font-size那篇文章中的解釋說明,它們的作用機制和原理都是一樣的,這里不在重復贅述。
我們來對上面所說的內容,做一些示例,來看看它們的實際工作方式。
先構建一個基本的代碼,之后都以這個為基礎改造和演示:
<div style="background-color: bisque;">
我是父元素
<div style="background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
看下現在的效果:
效果
記住這個效果,因為我們接下來就要改變contain屬性,觀察它所發生的變化。
<div style="contain: size;background-color: bisque;">
我是父元素
<div style="background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
給父元素加上contain:size樣式:
效果
可以看到,"我是父元素"和"我是父兄弟元素"重合了,也就說,父兄弟元素的渲染,直接從父元素渲染開始的位置開始渲染的。就好像父元素不存在一樣。
這里面的奧妙通過控制臺看一下,其實就很容易解開了:
效果
就是因為父元素的高度為0了。在解釋之前先說明一下,行向指的是我們書寫的方向,就是指的從左往右,你就可以理解成是多個行內元素排列的方向,一直往后面追加的方向。塊向指的是我們折行的方向,也就是指的從上往下,你就可以理解成是多個塊級元素排列的方向,一直往下追加的方向。
理解了這兩個之后,我們就知道,由于size影響著這兩個方向上的局限,它會變得無視子元素。因為如果沒有主動設置尺寸的話,就好像子元素不存在一樣,那么它就沒有高度,所以兄弟元素就自然而然的頂上來了。
這時,我們改一下設置,讓它只在行向上有局限:
<div style="contain: inline-size;background-color: bisque;">
我是父元素
<div style="background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
通過設置contain:inline-size:
效果
可以看到,效果又回來了,這是因為我們沒有在塊向上做局限,因此高度會自然撐開。
既然說到了這里,我們再看一下,它是如何在行向上進行局限的,構造如下代碼:
<div style="contain: inline-size;display: inline-block;background-color: bisque;">
我是父元素
<div style="background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
設置父元素為行內塊,增加display:inline-block:
效果
瞬間又變成了這樣,這同樣是因為,行內局限使得父元素獨立計算尺寸,而我們又沒手動指定,因此它的寬度為0,子元素也跟著寬度為0,所以就變成了一個字一換行。
這時即使你給子元素加上寬度,在行向上父元素也會無視你:
效果
你看我們給子元素加上100px的寬度,但是鼠標查看父元素,依然是寬度為0。
指定contain:layout,可以讓該元素獨立計算它的內部布局,不受外界影響,我們先將子元素設定一個固定定位:
<div style="background-color: bisque;">
我是父元素
<div style="position: fixed;top: 10px;background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
看下現在的效果:
效果
完全沒毛病,子元素固定到頁面頂部的10px位置。
現在應用一下我們的布局限制:
<div style="contain: layout;background-color: bisque;">
我是父元素
<div style="position: fixed;top: 10px;background-color: coral;">
我是子元素
</div>
</div>
<div style="background-color: lightpink;">
我是父兄弟元素
</div>
再看下顯示的效果:
效果
咦?明明是固定定位,它的位置卻是相對于父元素的。這就是布局限制的作用,相當于父元素告訴頁面,從現在開始,這片的布局歸我管,所有的行為都向我請示,由我指揮。
同樣,其他的position值,也都是基于父元素的布局限制來渲染的,這里就不做一一演示了。
其實,不光是position,只要是關于布局的,都會在此局限下生效,這里再演示一個浮動的例子:
<div style="height: 80px;padding: 5px;background-color: bisque;">
<h2 style="margin-bottom: 7px;">我是父元素</h2>
<p style="float: left;background-color: coral;">
我是子元素
</p>
</div>
<div style="height: 80px;padding: 5px;background-color: lightpink;">
<h2>我是父兄弟元素</h2>
<p style="background-color: coral;">
我是父兄弟子元素
</p>
</div>
兩個父元素各包含兩個子元素,其中第一個父元素的第二個子元素設置為左浮動,為了更好的演示,我把子元素改成了h2和p標簽,看下現在的效果:
效果
父元素的兩個子元素正常顯示,但是父兄弟元素的第一個子元素里面的文字,被擠的偏移了,這是由于父元素的第二個子元素設置浮動引起的,通過控制臺看下就明白了:
效果
紅線是我標出來的,可以看到,父兄弟元素的h2和父元素的浮動有一丁點的重合,導致文字被推開,這就是浮動產生的影響。
我們通過布局局限,來控制浮動只發生在局限內,稍微改下代碼:
<div style="contain: layout;height: 80px;padding: 5px;background-color: bisque;">
<h2 style="margin-bottom: 7px;">我是父元素</h2>
<p style="float: left;background-color: coral;">
我是子元素
</p>
</div>
<div style="height: 80px;padding: 5px;background-color: lightpink;">
<h2>我是父兄弟元素</h2>
<p style="background-color: coral;">
我是父兄弟子元素
</p>
</div>
給父元素添加了contain:layout,這是浮動就不會影響后面的布局了:
效果
通過布局局限,我們可以把所有的關于布局的影響,都控制在容器內,這樣即使容器內布局發生了改變,也完全不會影響頁面其他內容,在動態頁面中,如果需要頻繁的修改某些元素,通過這種方式管理和設計頁面,就能很有效的改善渲染的性能。
這里的樣式主要是針對計數器和引號的作用域,能控制它們只在所局限的范圍內單獨計算,而不會影響全局的結果,就好像它們是單獨拿出來作為一個獨立的文檔一樣,看個例子:
body {
counter-reset: my-list;
}
div > div::before {
counter-increment: my-list;
content: "(" counter(my-list) "):";
}
<div>
<div>第1行</div>
<div>第2行</div>
<div>第3行</div>
<div>第4行</div>
<div>第5行</div>
<div>第6行</div>
</div>
我們設計這樣一個列表,通過自定義的計數器,設置一個前綴的顯示:
效果
如果我們希望第三行獨立出來,進行樣式局限,不參與外部計數:
<div>
<div>第1行</div>
<div>第2行</div>
<div style="contain: style;">第3行</div>
<div>第4行</div>
<div>第5行</div>
<div>第6行</div>
</div>
那么它就會展現成這個樣子:
效果
注意第三行的計數,已經重置為1,并且第四行從3開始,接著第二行的值繼續計數。
這個也比較厲害,就是父元素啥樣就是啥樣,子元素永遠不會在容器外渲染:
<div style="background-color: bisque;width: 100px;height: 100px;">
<div>
海客談瀛洲,煙濤微茫信難求。
越人語天姥,云霞明滅或可睹。
天姥連天向天橫,勢拔五岳掩赤城。
</div>
</div>
有這樣一個代碼塊,容器的寬高為100px,內容有超出部分:
效果
我們可以通過繪制局限來使容器外的內容不顯示:
<div style="contain: style;background-color: bisque;width: 100px;height: 100px;">
<div>
海客談瀛洲,煙濤微茫信難求。
越人語天姥,云霞明滅或可睹。
天姥連天向天橫,勢拔五岳掩赤城。
</div>
</div>
添加contain:paint,只讓繪制區域被限制在容器內部:
效果
這個跟overflow:hidden有一點區別,就是繪制局限真的就是正常繪制,只不過不繪制容器外的部分,而hidden雖然隱藏,但是依然能通過js進行滾動。
我們也可以通過任意的值的組合來控制所需要的局限,也可以通過strict或content關鍵字來快速的做到這一點。這里就不再重復演示了
合理的使用contain,不但能快速實現我們的需求,也能減少我們的修改量,而且會降低不理解現象的情況的出現頻率,更能提升頁面的性能。
尤其是布局局限,提供給了我們更多的發揮空間,而且任意的復制到其他地方,也不會對外部元素有影響。
每天一點小知識,希望能夠幫助到你。
flex 模態框彈窗浮動垂直水平居中
- position:fixed 定位
- 元素的位置相對于瀏覽器窗口是固定位置。
- 即使窗口是滾動的它也不會移動;
HTML 代碼實例
```
求:當頁面很長,有滾動條時,需要固定頁面上的部分元素,便于下方元素和上方固定元素的對照。
起始頁面布局
固定效果
*請認真填寫需求信息,我們會在24小時內與您取得聯系。