CSS3 transform 對HTML文檔流帶來的影響

html 老是那麼的驚奇css

來源於「硬件加速」

年初的一個筆記,閒時整理出來。html

不少網上文章都說建議打開瀏覽器的硬件加速,這樣頁面渲染速度、動畫流暢性會提升。這幾乎成了不少人頁面製做的標配,管實際有沒有用都來一個:css3

html,body {
        transform: translate3d(0,0,0);
    }

但這在不少狀況下會引發 html 層級文檔流的「異常」。
W3C spec 中有以下描述:git

In the HTML namespace, any value other than none for the transform results in the creation of both a stacking context and a containing block.
The object acts as a containing block for fixed positioned descendants.github

意思是:
在 HTML 內,沒有比對一個便是層疊對象又是容器塊的 DOM 進行 transform 變換更沒有意義的了。
這類對象也扮演着 positioned(主要是 absolute/fixed ) 子孫元素容器的角色。web

。。。翻譯能力有限,不理解的人估計這句話看了後更暈,下面詳述。瀏覽器

標準文檔流

頁面中的 dom 元素按照其在 HTML 中的標籤位置順序進行從上到下、從左往右的排布過程dom

想必你們對這個基礎的定義已經很熟悉了吧。可是,這個究竟在實際中有什麼體現呢?ide

若是你在頁面中放置一大堆 display: inline-block 的元素,它們會很乖巧的 上 -> 下 左 -> 右 排的很整齊。這就是標準文檔流的基礎體現。動畫

當你用positionfloat等屬性使其脫離文檔流時,就會又產生一個頁面 層級 的概念。(扯遠了...)

transform 改變定位默認屬性

例子代碼以下:

<body>
        <header style="position: fixed; top: 0; width: 100%; background: red;">header</header>
        <div style="height: 2000px;"></div>
        <footer style="position: fixed; bottom: 0; width: 100%; background: blue;">footer</footer>
    </body>

點擊查看例子

dom 元素的默認定位屬性是 position: static; 這也是標準文檔流的標準定位方式。

例子中,無論 div 怎麼上下滾動,header 和 footer 會永遠置於屏幕的最上和最下部。

可是如最初所述,給 bodyhtml 加上一個 transform: translate3d(0,0,0);,你再去試,就會發現,本來 position: fixed; 的兩個元素都不聽話了,會隨着屏幕進行滾動。

實際上,position: fixed; 的參考對象並非你們所說的屏幕,而是一個 viewport 的html對象,通常地一個頁面(document.documentElement)會生成一個 viewport。

你用 document.documentElement.clientHeight 就能夠的看到實際 viewport 的高度,其中 fixed 的元素都是以此爲容器進行定位的。

body(或html) 加了 transform 屬性之後,整個 body DOM 既會產生相應的變換,但此時的「整個」僅是指 body 下標準文檔流元素,對於那些 position: absolute; / position: fixed; 元素,由於已經脫離了 body 所屬的文檔流,因此沒法憑藉 body 的變換使本身也天然的達到相應的變換效果。

此時,瀏覽器爲了讓此類 DOM 獲得相應的變化,會產生一個新的 viewport,這個 viewport 做爲定位元素的容器存在,會響應 body 的 transform 變換效果,從而讓裏面那些脫離文檔流的 positioned 元素也能進行變換。

這個 viewport 會嚴重影響 position: fixed; 的定位,當它隨着「本尊」dom同步滾動的時候,會帶着 fixed 元素一塊滾,此時會產生一種相似 absolute 的詭異效果:

fixed 元素彷佛變成了 absolute,存在於一個和document.documentElement大小一致的「看不見」容器內。

引伸狀況

在一些移動端設備(或APP)上,給 <video> 標籤的播放默認開啓的硬解碼,此時也會產生上述現象,視頻會"浮"在頁面上面,不會隨頁面元素正常滾動。

還有一些低版本移動端瀏覽器上,也會出現相似的狀況,可按此思路嘗試解決。

總結

其實上面的狀況不僅會發生在 body 上,一個任意的 dom 添加了 transform 以後都會生產一個相似 viewport 的效果,有興趣能夠去嘗試。

引用:
http://meyerweb.com/eric/thoughts/2011/09/12/un-fixing-fixed-elements-with-css-transforms/

相關文章
相關標籤/搜索