在iOS Safari

时间:2018-02-19 20:14:14

标签: css svg mobile-safari

编辑:删除了dev链接,放弃了这个问题。

我一直试图解决看似微不足道的渲染问题一周,并且已经用尽所有选择,这是我的求救之情。我已经阅读了有关SO的所有相关问题,但仍无法解决此问题。

目标
我的目标是在网页上内嵌呈现简单对称形状的SVG图标。 SVG位于一个包装器内,它有一个背景颜色和一些填充。这就是正确的渲染效果:

enter image description here

上面是Chrome中放大视图的正确渲染内容。注意图标是如何正确定位的,它不以任何方式偏离中心。

请注意,我特意使用小填充和大对比度来显示问题,因为这是一个微妙但令人不安的问题。

问题
上述正确的渲染在Windows(Firefox,Chrome,Edge)上的桌面浏览器以及Android上的Chrome和Firefox中都是一致的。它只在iOS Safari上呈现不正确。这是一个错误渲染的例子:

enter image description here

以上是来自iPhone 6S,iOS 11的放大屏幕截图。这些是同一页面上同一图标的3个实例。请注意每个演绎在偏离中心时的错误方式。还要注意它是如何在偏离中心的情况下保持一致的,它似乎几乎是随机的。

图标本身
图标本身来自Symbolicons。我检查了矢量本身,以确保它没有间距: enter image description here

它接触边框,几何形状适合24x24的视图框。我在这个图标包中检查了一些其他图标,我和其他图标面临同样的问题,但仅限于iOS Safari。所以我不认为SVG本身存在问题。

问题详情
关于iOS Safari行为的更多细节。我在iOS 10和11,iPhone 5,iPhone 6S,iPad Pro 10",iPad Pro 12"上进行了测试。渲染的不正确性似乎与设备的大小及其方向不同。例如,iPhone5是唯一具有完美渲染效果的产品,但是当将其转换为横向模式并刷新页面时,它就会失败。在iPad上,它几乎总是失败但它可以与子像素不同,取决于屏幕的大小和方向。

这种行为或许暗示某些缩放效果正在发挥作用。

稳固基线
我将这些图标集成在一起的页面相对复杂,可能有很多因素影响渲染,所以我从一个最小的测试用例开始:

https://codepen.io/fchristant/pen/PQKWww

我在所有iOS设备上测试了这个codepen,它们可以在任何场景中实现完美渲染,而不会出现偏心问题。注意codepen如何使用像素而不是相对值来完全控制渲染:

.icon-wrap {
    display:block;
    background:green;
    margin:0;
    padding:0;
    width:16px;
    height:16px;
    border:1px solid red;
    box-sizing:content-box;
    padding:4px;
    margin-bottom:20px;
}

.myicon {
    display:block;
    width:100%;
    height:100%;
    padding:0;
    margin:0;
    border:1px solid purple;
    box-sizing:border-box;
}

此外,包装器和SVG都是display:block,以避免任何间距问题。

如上所述,这个最小测试用例非常有效。这意味着可以在移动Safari上正确呈现此场景。

然而,当将它集成回我的页面时,它就失败了。我花了好几天在我的页面中追逐可能会影响它的条件,并且我的选项已经用完了。以下是我尝试过的一些事情:

  • 在SVG上设置宽度/高度,尽管在CSS中也有。似乎并不重要。
  • 在SVG上为preserveAspectRatio尝试不同的值:没有区别
  • 设置SVG版本:无差异
  • 位置相对/绝对的变化:没有差异
  • 代替宽度/高度:100%,使用硬编码像素:无差异
  • 将其放置在特定的布局容器或外部(flexbox,网格):有时会更改渲染,但仍然无法始终如一地纠正。
  • 使用元视口值:无差异
  • 为形状渲染尝试不同的值:没有区别

我认为这可能是一个子像素舍入问题,但从逻辑上说这没有任何意义。我到处都使用硬编码的可分割2像素值。另外,原始的codepen工作。

底线:在工作的代码笔和我的测试页之间,有一些竞争条件触发了不正确的渲染,尽管经过了数天的搜索,我还是找不到它。

测试页
这是测试页面: [除去]

它在我的开发服务器上。如果有问题,我会尽力保持这个问题。你可以找到" globe"图标位于页面上的某些缩略图上。不幸的是,您只能在真实的iOS设备上看到问题,并且只能尽可能放大。

是的,我知道为解决这么小的问题付出极大的努力似乎很荒谬,但这个真的让我失望了。一旦你看到它就会像拇指一样伸出来。另外,知道Safari可以正确渲染它,如codepen中所示,这让我有希望解决这个问题。

我非常感谢结构修复。我曾尝试过一次性修复,例如在外部布局容器上减少或增加1px的大小。这些解决方案在一个设备/方向上解决它,但在其他方案中产生新问题。我希望不管在哪种情况下我都会提供这样的图标。所有浏览器都可以做到,但不是移动Safari。好吧,Safari可以(参见codepen),然而我正在做的事情会导致它表现得很糟糕,我不知道它是什么。

编辑:建议用CSS框替换SVG,看看这是否也会受到渲染故障的影响。这是这种情况的截图,它完美呈现:

enter image description here

所以它看起来确实与SVG有关。

3 个答案:

答案 0 :(得分:1)

好吧,试试这个......

我看到包裹span的{​​{1}}和width等于height尺寸。但是你有1px填充。不幸的是,这是盲人,因为我们无法自己测试。试试这个:

svg

答案 1 :(得分:1)

这可能是一个非常类型的答案,但它可能帮助..虽然它有点hacky ..我只是建议这个答案,因为它似乎你有其他所有其他工作除了safari之外的浏览器,如果你修补过多,你可能会对其他浏览器产生新的问题。

您可以尝试使用javascript和一些jquery来帮助解决您的问题。您可以使用它们来检测您所使用的浏览器,并从那里可以对样式进行微调。您也可以检测横向模式。这是一个stackoverflow的答案,可以帮助您开始探索如何检测浏览器:

How to detect Safari, Chrome, IE, Firefox and Opera browser?

一旦你弄清楚如何检测safari,你可以使用jquery将css样式应用于你的div和图像。所以无论你对safari中的div做什么,都不会干扰你在其他浏览器上所做的工作。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
    $(document).ready(){

        var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && safari.pushNotification));

        if (isSafari) {
            if(window.innerHeight > window.innerWidth){
                //portrait mode
                $('.icon-wrap').css({
                    ... your css for safari code here ...
                });

                $('.myicon').css({
                    ... your css for safari code here ...
                });
            } 
            else {
                //landscape mode
                $('.icon-wrap').css({
                    ... your css for safari code here ...
                });

                $('.myicon').css({
                    ... your css for safari code here ...
                });
            }
        }
    }
</script>

答案 2 :(得分:1)

免责声明:我要回答,因为我没有发表评论的声誉,但是我无法知道这是否可以解决OP的特定问题,此外,这不是解决方案,而是更多解决问题的探索方向。

我知道这个问题现在已经很老了,但是我在Safari中为iOs遇到了SVG对齐问题,并且设法用一些JavaScript解决了这个问题。由于测试页不见了,因此我无法评论如何在您的特定情况下应用它,但这是一个主意:

通过四处查看,我注意到在iOs上的Safari在我想将其他SVG元素居中放置的元素上调用getBoundingClientRect()时返回错误的尺寸和位置。我将呼叫置于具有250 ms延迟的超时中,然后返回正确的边界矩形,然后可以在浏览器之间正确且一致地对齐元素。关键是Safari的SVG定位代码中似乎存在竞争条件,因此也许该错误也会影响您的图标。

如果这可以在您的项目环境中使用,我建议尝试强制Safari在DOM加载后几百毫秒内重新布局SVG。