zoukankan      html  css  js  c++  java
  • Safari 3D transform变换z-index层级渲染异常的研究

    一、Safari是新时代的IE6

    在2年前介绍currentColor变量的时候就提过Safari的问题,就是伪元素hover时候的currentColor不渲染,

    像这种IE浏览器都可以正常渲染的CSS,Safari居然出现各种匪夷所思的问题,对的,是各种,而且全都是与渲染相关的,这也难怪为什么Safari浏览器被称为“新时代的IE6”了!

    补充于2016-08-09
    Safari font-size的px单位和vm单位计算不支持,需要是百分比单位,可参见这篇文章
    Safari 渐变,从#fff到transparent会有灰色带,其他浏览器都是白色到透明。

    或许,很早的时候,Safari和IE有段暧昧不清的过往(看下图的攻受表情):
    Safari和IE

    本文即将介绍的渲染问题,也是仅Safari浏览器才有的,是我同事遇到的,我觉得很有意思,忍不住拿来和大家分享下。

    二、Safari 3D变换会忽略z-index的层级

    在Safari浏览器下,此Safari浏览器包括iOS的Safari,iPhone上的微信浏览器,以及Mac OS X系统的Safari浏览器,当我们使用3D transform变换的时候,如果祖先元素没有overflow:hidden/scroll/auto等限制,则会直接忽略自身和其他元素的z-index层叠顺序设置,而直接使用真实世界的3D视角进行渲染。

    我们直接看例子,如果您现在用的是iMac或air或iPad或iPhone之类的苹果设备浏览本文,您可以狠狠地点击这里:Safari浏览器下3D transform和z-index层级渲染demo

    如果高度不够页面滚动,请双指放大页面比例,让图片和红色条子(fixed定位)发生重叠,就会看到很有趣的渲染效果。

    如果您是window系统的浏览器上浏览本文,但是手上有iPhone,也可以使用微信等app扫描访问:
    demo页面二维码

    不出意外,滚动页面,会看到类似下面这样的渲染效果:
    渲染异常显示截图

    会看到,红色的块状条子,从图片中心穿过去了。实际上,这个红色条子是层级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旋转,那自然红色条子就从中心穿过,而且视角背后的内容是看不见的。

    算了,别继续开脑洞了,来看看这个问题该如何解决吧~~

    三、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)效果截图

    喔噢,这下图片完全被红色的长条子覆盖了,这下,所有浏览器的表现都是一模一样的啦!

  • 相关阅读:
    LeetCode 83. Remove Duplicates from Sorted List (从有序链表中去除重复项)
    LeetCode 21. Merge Two Sorted Lists (合并两个有序链表)
    LeetCode 720. Longest Word in Dictionary (字典里最长的单词)
    LeetCode 690. Employee Importance (职员的重要值)
    LeetCode 645. Set Mismatch (集合不匹配)
    LeetCode 500. Keyboard Row (键盘行)
    LeetCode 463. Island Perimeter (岛的周长)
    115.Distinct Subsequences
    55.Jump Game
    124.Binary Tree Maximum Path Sum
  • 原文地址:https://www.cnblogs.com/qidian10/p/6582247.html
Copyright © 2011-2022 走看看