o2team / H5Skills

移动端开发技巧集合
831 stars 80 forks source link

一个 mask-border 在安卓机的 hack 的发现之旅 #41

Open leeenx opened 7 years ago

leeenx commented 7 years ago

mask-border 在安卓下失效的BUG

上周,同事反馈了一个使用 mask-border 在华为荣耀3c机子下矢效的BUG。由于本人写过关于 mask 与 mask-border 的文章: https://aotu.io/notes/2016/10/19/css3-mask/ ,并也是主张推广它的人,所以解决这个BUG是当务之急。

注意了,本文的hack是针对 x5 内核而言

出问题的页面使用了我的文章里介绍的方法,但是却出现了如下BUG:

正常的显示是(ip6):

对应的关键代码如下:

.mask::after {
    content: ''; 
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    height: 100px;
    z-index: 3;
    background-color: #ff0;
    pointer-events: none;
    mask-border: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8AQMAAAAAMksxAAAABlBMVEUAAADxVZe4xg/eAAAAAXRSTlMAQObYZgAAAFdJREFUKM9j+H/8Pwh8YGhwYWBgYFIQwMdo/3+AgcH+nwBDi4sDA4OSEjbGf7AaoIEsYF1KDJgMuBp85rQfB6qxswPazgAGw44B9SAdAhMRccTEMjxJAACiVld1wtGnfgAAAABJRU5ErkJggg==) 18/9px stretch;
}

经过遂节点排查,居然发现当页面节点比较多的情况下 mask-border 会失效 -_-|||,这感觉是个没有办法解决的BUG。

另一个BUG

我自己当前正好有一个年货二期的页面,今天(2016.12.26)在ip6在体验时,发现页面巨卡,但是在安卓下(华为荣耀3c)却又不卡!!!

通过定位发现是 drop-shadow 导致 iOS 下的卡顿,毕竟 drop-shadow 也是一个 filter,滤镜在 iOS 下是比较占资源的!!于是把这个 drop-shadow 去掉后解决了卡顿的BUG。

但是,我意外地发现:如果把滤镜去掉后,安卓下 mask-border 会失效。 如下:

未去滤镜之前的样子如下:

drop-shadow 是一个 filter 那么我加个 blur(0) 是不是可以解决这个BUG? 答案是肯定的!!!

不过,这个 filter: blur(0) 需要放在 mask-border 的父节点上才可以生效。基于这点,针对 低端安卓机 写一个 hack:

.mask {
    filter: blur(0);
    transform: translate3d(0, 0, 0);
    @supports(-webkit-mask-repeat: repeat) {
        // 高端安卓 与 ios 能识别
        filter: none;
    }
}

.mask::after {
    content: ''; 
    position: absolute; 
    top: 0;
    left: 0;
    width: 100px;
    height: 100px;
    z-index: 3;
    background-color: #ff0;
    pointer-events: none;
    mask-border: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8AQMAAAAAMksxAAAABlBMVEUAAADxVZe4xg/eAAAAAXRSTlMAQObYZgAAAFdJREFUKM9j+H/8Pwh8YGhwYWBgYFIQwMdo/3+AgcH+nwBDi4sDA4OSEjbGf7AaoIEsYF1KDJgMuBp85rQfB6qxswPazgAGw44B9SAdAhMRccTEMjxJAACiVld1wtGnfgAAAABJRU5ErkJggg==) 18/9px stretch;
}

将这段代码放到 mask-border 失效的页面,成功解决BUG。

最终的hack

笔者在解决BUG的过程中发现,如果 mask-border 的父节点的结构比较复杂的话,单纯使用 filter 也不能解决问题,这个时间需要现加一个 3d 加速才可以完全解决问题,所以我写的hack如下:

%mask-border-hack {
    filter: blur(0);
    transform: translate3d(0, 0, 0);
    @supports(-webkit-mask-repeat: repeat) {
        // 高端安卓 与 ios 能识别
        filter: none;
    }
}

上面hack生效有个前提,mask-border不能使用3d加速

安全建议

由于观察的情况有限,也不能保证上面代码的 100%有效。我个人建议使用另一种比较保险的做法,就是 mask-border 放在一个单独的 div 下,这样子就可以 100% 保证上面 hack 生效。如下:

不过,我现在观察的情况有限,也不能保证上面代码的 100%有效。我个人建议使用另一种比较保险的做法,就是 mask-border 放在一个单独的 div 下,这样子就可以 100% 保证上面 hack 生效。如下:

<style>
.mask {
    filter: blur(0);
    transform: translate3d(0, 0, 0);
    @supports(-webkit-mask-repeat: repeat) {
        // 高端安卓 与 ios 能识别
        filter: none;
    }
}

.mask::after {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100px;
    height: 100px;
    z-index: 3;
    background-color: #ff0;
    pointer-events: none;
    mask-border: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8AQMAAAAAMksxAAAABlBMVEUAAADxVZe4xg/eAAAAAXRSTlMAQObYZgAAAFdJREFUKM9j+H/8Pwh8YGhwYWBgYFIQwMdo/3+AgcH+nwBDi4sDA4OSEjbGf7AaoIEsYF1KDJgMuBp85rQfB6qxswPazgAGw44B9SAdAhMRccTEMjxJAACiVld1wtGnfgAAAABJRU5ErkJggg==) 18/9px stretch;
}

</style>

<!-- 把box的::after转移动到 mask 的 ::after 中去,再加 mask 加一个hack  -->
<div class=“box”>
    <div class=“mask”></div>
</div>