Safari 3D transform變換z-index層級渲染異常的研究

1、Safari是新時代的IE6

在2年前介紹currentColor變量的時候就提過Safari的問題,就是僞元素hover時候的currentColor不渲染,html

像這種IE瀏覽器均可以正常渲染的CSS,Safari竟然出現各類匪夷所思的問題,對的,是各類,並且全都是與渲染相關的,這也難怪爲何Safari瀏覽器被稱爲「新時代的IE6」了!css3

補充於2016-08-09
Safari font-size的px單位和vm單位計算不支持,須要是百分比單位,可參見這篇文章
Safari 漸變,從#fff到transparent會有灰色帶,其餘瀏覽器都是白色到透明。瀏覽器

或許,很早的時候,Safari和IE有段曖昧不清的過往(看下圖的攻受表情):
Safari和IE微信

本文即將介紹的渲染問題,也是僅Safari瀏覽器纔有的,是我同事遇到的,我以爲頗有意思,忍不住拿來和你們分享下。app

2、Safari 3D變換會忽略z-index的層級

在Safari瀏覽器下,此Safari瀏覽器包括iOS的Safari,iPhone上的微信瀏覽器,以及Mac OS X系統的Safari瀏覽器,當咱們使用3D transform變換的時候,若是祖先元素沒有overflow:hidden/scroll/auto等限制,則會直接忽略自身和其餘元素的z-index層疊順序設置,而直接使用真實世界的3D視角進行渲染。wordpress

咱們直接看例子,若是您如今用的是iMac或air或iPad或iPhone之類的蘋果設備瀏覽本文,您能夠狠狠地點擊這裏:Safari瀏覽器下3D transform和z-index層級渲染demospa

若是高度不夠頁面滾動,請雙指放大頁面比例,讓圖片和紅色條子(fixed定位)發生重疊,就會看到頗有趣的渲染效果。3d

若是您是window系統的瀏覽器上瀏覽本文,可是手上有iPhone,也可使用微信等app掃描訪問:
demo頁面二維碼code

不出意外,滾動頁面,會看到相似下面這樣的渲染效果:
渲染異常顯示截圖

會看到,紅色的塊狀條子,從圖片中心穿過去了。實際上,這個紅色條子是層級99的position:fixed定位的元素:

.bar {
    position: fixed; 
    /* Safari下z-index無效 */
    z-index: 99;
}

而圖片就是一個小白圖片,沒有定位屬性的設置,就一個簡單的帶有視角的3D旋轉變換:

img {
    transform: perspective(300px) rotateY(40deg);
}

按照CSS規範上的說明,紅色條子應該在圖片上面,相似下面這樣:
Chrome瀏覽器下截圖

IE, Chrome, FireFox都是遵循這種渲染的,可是,Safari瀏覽器卻本身任性了一把。直接把z-index:99給無視了,對無視了,在座的諸位也不要懷疑是否是99還不夠大,就算是9999999這是這般渲染,由於Safari是忽略z-index,而不是IE6,IE7那種z-index計算bug.

根據我本身的理解,Safari的這種渲染或許並不能直接稱之爲bug, 由於,從某些角度講,Safari的這種渲染挺符合符合現實3D世界。

我本身YY了一下,Safari若是沒有overflow的限制,就會把2次元頁面變成真實的3次元,本來圖片和紅色條子在一個面上,當圖片進行了3D旋轉,那天然紅色條子就從中心穿過,並且視角背後的內容是看不見的。

算了,別繼續開腦洞了,來看看這個問題該如何解決吧~~

3、Safari 3D變換會忽略z-index問題解決

方法1:
父級,任意父級,非body級別,設置overflow:hidden可恢復和其餘瀏覽器同樣的渲染。

方法2:
以毒攻毒。有時候,頁面複雜,咱們不能給父級設置overflow:hidden,怎麼辦呢?

楊過的情花劇毒怎麼解的?斷腸草啊,另外一種劇毒。這裏也是相似。既然「穿越」的渲染問題是由3D transform變換產生的,那麼,要解決此問題,咱們也可使用3D transform變換。

那具體該如何作呢?

我在「好吧,CSS3 3D transform變換,不過如此!」一文中就科普過z軸的概念。

咱們仔細觀察下面這張效果截圖:
渲染異常顯示截圖

咱們的紅色條子在z軸位置0處,對不對,因此才從圖片的中心穿過。而z軸是咱們眼睛看屏幕這條軸,在z軸的值越大,就離用戶的眼睛越近;值越小,裏用戶眼睛越小。所謂近大遠小(若是指定了視角perspective),就是這麼回事。

網頁中z軸示意

因此,咱們要想讓紅色條子覆蓋在圖片上,只要設置一個足夠大的translateZ值就能夠,如100px

.bar {
    position: fixed;
    z-index: 99;
    /* 以毒攻毒 */
    transform: translateZ(100px);
}

結果:
translateZ(100px) 的效果截圖

咦,尷尬,好像仍是不夠大,圖片還有一點點位置在紅色條的上面~~ 

趕快用120px試試:

.bar {
    position: fixed;
    z-index: 99;
    /* 以毒攻毒 */
    transform: translateZ(120px);
}

結果:
translateZ(120px)效果截圖

喔噢,這下圖片徹底被紅色的長條子覆蓋了,這下,全部瀏覽器的表現都是如出一轍的啦!

相關文章
相關標籤/搜索