1. 程式人生 > >transform與position:fixed的那些恩怨

transform與position:fixed的那些恩怨

str 成了 情況 containe 對象 main object 例如 ack

1. 前言

在寫這篇文章之前,我理解的fixed元素是這樣的:(摘自CSS布局基礎)

固定定位與absolute定位類型類似,但它的相對移動的坐標是視圖(屏幕內的網頁窗口)本身。由於視圖本身是固定的,它不會隨瀏覽器窗口的滾動條滾動而變化,除非你在屏幕中移動瀏覽器窗口的屏幕位置,或改變瀏覽器窗口的顯示大小,因此固定定位的元素會始終位於瀏覽器窗口內視圖的某個位置,不會受文檔流動影響,這與background-attachment:fixed?屬性功能相同。

但是直到我看到這篇文章CSS 為什麽這麽難學?,作者在文章中提到了一個“黑魔法”,如何讓fixed元素不再以viewport為定位參考對象,而是以父容器為參考對象。這下子我算是get到了一個技能。唯一不認同作者的是,他提到的CSS“不正交”,不好學,其實我認為根本原因是知識基礎不夠紮實罷了。凡事都有個原理,不可能無緣無故冒出一個科學解釋不了的對象的。

於是這裏我們打算以這個知識點為基礎,去探討為什麽會這樣然後寫了一個比較使用的例子,在移動端用的可能會比較多。

2. 為什麽fixed元素的父元素加了transform就會以父元素為參考對象?

詳細的demo如下:

查看這個demo發現,我們在父元素設置了transform: scale(1);這個屬性,然後其子元素fixed-to-container便以父元素為參考對象了,而且不再固定在某個地方,而是會隨著文檔流的流動而流動。

這是為什麽呢?

答案在設置了transform屬性的元素上,在W3c文檔上transform屬性,文檔的定義翻譯如下:

對於布局受CSS盒子模型控制的元素,transform屬性不會影響transformed元素周圍的內容流。但是,溢出區域的範圍將會考慮上transform元素。這種行為類似於元素通過相對定位發生偏移時的情況。因此,如果overflow屬性的值是`scroll``auto`的,滾動條將顯示為需要看到在可見區域外轉換的內容。

對於布局受CSS盒子模型控制的元素,除了配置為`none`之外,其他的`transform`屬性值都會創建堆棧上下文。繪制的實現必須在其父棧上下文中它所創建的層中,如果它是帶有“z-index: 0”的定位元素,則使用相同的堆疊順序。如果一個帶有`transform`的元素還配置了`position`屬性,那麽“z-index”屬性將按照[CSS2](https://www.w3.org/TR/css-transforms-1/#biblio-css2)描述的被應用,除非“auto”被視為“0”,因為會創建新的堆棧上下文。

對於布局受CSS盒子模型控制的元素,除了配置為`none`之外,其他的`transform`屬性值都將導致元素成為一個包含塊,而其固定定位的後代元素都是以此object作為他們的包含塊。

根元素的[Fixed Backgrounds](https://www.w3.org/TR/css3-background/#fixed0)會受到該元素上配置的transform屬性的影響。對於受transform影響的所有其他元素(例如,對它們應用transform屬性,或者對它們的任何祖先元素應用transform屬性),  `background-attachment`屬性值為`fixed`的元素會被當做它好像有配置`scroll`屬性一樣。其他`background-attachment`的計算值不受影響.

在這段介紹中我們發現transform會對fixed屬性造成影響。具體表現可以看上面的那個demo。

簡單來說就是:應用了transform屬性的元素會導致該元素形成一個新的包含塊,然後其後代元素如果有fixed定位的屬性,那麽其元素將會以該父元素作為包含塊,從而有了之前我們看到的現象。

除了上述說的,我還是發現了另外兩個特征:

  1. fixed元素不在固定在某個位置,失去了fixed元素特有的性質
  2. fixed元素不會脫離文檔流,但是top等屬性依然可用。可以看例子中的top屬性,配置了top:10px;整個文檔流都往下走10px;

3. 真的fixed元素,但是不以viewport為參考

這裏說的真的fixed元素,是真的可以固定在某個位置,其他元素可以從其下面穿梭過去。在實際的項目中有一個很常見的需求,如下面的demo:

在demo中,我們點擊按鈕會彈出一個面板,在面板的最上面會有一個fixed的頭部,面板的其他地方可以自由滑動,這種案例相信很多童鞋都會用到。

按照我們之前的說法,形成了這麽一個解決方案。

不過不清楚這種做法是否是最佳的?精通CSS的童鞋是否有更好的做法呢?不吝賜教。

transform與position:fixed的那些恩怨