We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
实锤了,Safari 就是新时代的 IE 浏览器。原因是有些东西在 Safari 渲染表现与预期(标准)不一致,而且 Safari for Mac 跟 Safari for iOS 的表现还不一定是相同的。
今天遇到了这样一个问题。举个例子,假设外层一个 max-width: 430px 的 section 元素,里面是一个 svg 元素,里面包含动画还有嵌套了一些元素。预期表现是:点击红色区域,绿色背景透明度匀速从 0 切换至 1。
<section style="max-width: 430px; margin: auto; overflow: hidden; font-size: 0"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="pointer-events: none; width: 100%; background-color: red"> <foreignObject x="0" y="0" width="100%" height="100%"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="opacity: 0; background-color: green"> <animate attributeName="opacity" begin="click" from="0" to="1" calcMode="linear" dur="1s" fill="freeze" restart="never" /> <rect x="0" y="0" width="100%" height="100%" fill="transparent" style="pointer-events: visible"> <set attributeName="visibility" begin="click" to="hidden" fill="freeze" restart="never" /> </rect> </svg> </foreignObject> </svg> </section>
body { margin: 20px; }
根据所设置的 viewBox="0 0 350 350"、preserveAspectRatio="xMidYMin meet" 以及 width: 100%,按道理的话,红色的 <svg> 及其内嵌套 <foreignObject> 和 <svg>,应该都是同等大小的正方形,而且取决于父元素 <section> 的宽度。
viewBox="0 0 350 350"
preserveAspectRatio="xMidYMin meet"
width: 100%
<svg>
<foreignObject>
<section>
是的,这个在 Chrome 表现没问题,但在 Safari for Mac 上就出现问题了,离奇的是 Safari for iOS 也是正常的。
如下图,此时 <body> 的宽度是大于 430px,因此 <section> 的宽度为 430px,自然 <svg> 的宽度就是 430px。
<body>
430px
但是,当我们点击蓝色框之外,红色区域(截图由于选中元素,该区域表现为橘色)以内的位置,你知道 Safari 定位到的元素是什么吗?
嗯......它定位到 <section> 元素了。意思就是说,内部的 元素区域并未覆盖到点击区,但我宽高明明设置的都是 100%,就很离谱。
100%
但是,我在右侧 Elements 选项卡选中 <rect> 元素时,它表现的区域明明就是占满的啊,也就是 430 * 430。
<rect>
430 * 430
Safari 你在玩我?
经多次测试,它可点击区域只有 350 * 350,也就是 viewBox 那个空间。
350 * 350
viewBox
由于是 Safari 的 bug,目前只能用一些治标不治本的方法,用魔法打败魔法。
给 <rect> 设置 transform: scale(2); transform-origin: left top;,其父级的 <svg> 设置 overflow: visible。由于 <foreignObject> 元素默认为 overflow: hidden,因此不用担心点击 430 * 430 之外的位置会触发事件。
transform: scale(2); transform-origin: left top;
overflow: visible
overflow: hidden
利用 <svg> 做了一个循环切换的交互,同样地,它在 Chrome 一切安好,而在 Safari 下则惊喜满满。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="width: 100%"> <foreignObject x="0" y="0" width="100%" height="100%"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="width: 100%"> <foreignObject x="0" y="0" width="100%" height="100%"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="opacity: 1; width: 100%; background-size: cover; background-image: url(https://cdn.jsdelivr.net/gh/toFrankie/blog/images/1682475354583.png); background-color: red"> <animate attributeName="opacity" begin="0s" keyTimes="0; 0.22222222; 0.33333333; 1" values="1; 1; 0; 0" calcMode="linear" dur="9s" repeatCount="indefinite" /> </svg> </foreignObject> <foreignObject x="0" y="0" width="100%" height="100%"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="opacity: 0; width: 100%; background-repeat: no-repeat; background-size: cover; background-position: top center; background-image: url(https://cdn.jsdelivr.net/gh/toFrankie/blog/images/1682475369330.png); background-color: green"> <animate attributeName="opacity" begin="0s" keyTimes="0; 0.22222222; 0.33333333; 0.55555556; 0.66666667; 0.666666670001; 1" values="0; 0; 1; 1; 0; 0; 0" calcMode="linear" dur="9s" repeatCount="indefinite" /> </svg> </foreignObject> <foreignObject x="0" y="0" width="100%" height="100%"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="opacity: 0; width: 100%; background-repeat: no-repeat; background-size: cover; background-position: top center; background-image: url(https://cdn.jsdelivr.net/gh/toFrankie/blog/images/1682475408407.png); background-color: blue"> <animate attributeName="opacity" begin="0s" keyTimes="0; 0.55555556; 0.66666667; 0.88888889; 0.99999999; 1" values="0; 0; 1; 1; 0; 0" calcMode="linear" dur="9s" repeatCount="indefinite" /> </svg> </foreignObject> <foreignObject x="0" y="0" width="100%" height="100%"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="opacity: 0; width: 100%; background-repeat: no-repeat; background-size: cover; background-position: top center; background-image: url(https://cdn.jsdelivr.net/gh/toFrankie/blog/images/1682475354583.png); background-color: red"> <animate attributeName="opacity" begin="0s" keyTimes="0; 0.88888889; 0.99999999; 1" values="0; 0; 1; 0" calcMode="linear" dur="9s" repeatCount="indefinite" /> </svg> </foreignObject> </svg> </foreignObject> </svg>
Safari 表现出「忽大忽小」的问题。如下图,灰色背景大小为 430 * 430,而红色背景处则是 350 * 350。
由于录制 GIF 太麻烦了,你可以使用 Safari 打开链接体验一下:https://codepen.io/tofrankie/full/abRWpaE。
由于 <foreignObject> 的坑,那就不要嵌套多层,所以可以这样处理,结构上也更清晰。
<section> <section style="height: 0"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="opacity: 1; width: 100%; background-size: cover; background-image: url(https://cdn.jsdelivr.net/gh/toFrankie/blog/images/1682475354583.png); background-color: red"> <animate attributeName="opacity" begin="0s" keyTimes="0; 0.22222222; 0.33333333; 1" values="1; 1; 0; 0" calcMode="linear" dur="9s" repeatCount="indefinite" /> </svg> </section> <section style="height: 0"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="opacity: 0; width: 100%; background-repeat: no-repeat; background-size: cover; background-position: top center; background-image: url(https://cdn.jsdelivr.net/gh/toFrankie/blog/images/1682475369330.png); background-color: green"> <animate attributeName="opacity" begin="0s" keyTimes="0; 0.22222222; 0.33333333; 0.55555556; 0.66666667; 0.666666670001; 1" values="0; 0; 1; 1; 0; 0; 0" calcMode="linear" dur="9s" repeatCount="indefinite" /> </svg> </section> <section style="height: 0"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="opacity: 0; width: 100%; background-repeat: no-repeat; background-size: cover; background-position: top center; background-image: url(https://cdn.jsdelivr.net/gh/toFrankie/blog/images/1682475408407.png); background-color: blue"> <animate attributeName="opacity" begin="0s" keyTimes="0; 0.55555556; 0.66666667; 0.88888889; 0.99999999; 1" values="0; 0; 1; 1; 0; 0" calcMode="linear" dur="9s" repeatCount="indefinite" /> </svg> </section> <section style="height: 0"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="opacity: 0; width: 100%; background-repeat: no-repeat; background-size: cover; background-position: top center; background-image: url(https://cdn.jsdelivr.net/gh/toFrankie/blog/images/1682475354583.png); background-color: red"> <animate attributeName="opacity" begin="0s" keyTimes="0; 0.88888889; 0.99999999; 1" values="0; 0; 1; 0" calcMode="linear" dur="9s" repeatCount="indefinite" /> </svg> </section> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 350" preserveAspectRatio="xMidYMin meet" style="width: 100%"></svg> </section>
这是 Webkit 的 Bug,相关链接:
该问题早在 2009 年就提出了,至今仍然没有任何进展,隔壁 Chromium 的 Blink 已在 2020 年 9 月修复。其中一个可复现的示例:https://codesandbox.io/s/chrome-foreignobject-defect-wf91j。在 Safari 打开使用 ⌘ + + 或 ⌘ + - 去缩放页面就能看到。
⌘
+
-
我用 Chrome 62 亲测了一下,确实也有问题,而且区域更小了。
简言之,根本原因就是 Safari/WebKit 无法正确渲染 <foreignObject> 中的 HTML 元素。
实锤了,Safari 就是新时代的 IE 浏览器。
The text was updated successfully, but these errors were encountered:
赞一个,但我还是没解决safari 兼容问题 渲染位置偏移,放大缩小后偏位更夸张,拖动元素偶尔出现残影
Sorry, something went wrong.
No branches or pull requests
实锤了,Safari 就是新时代的 IE 浏览器。原因是有些东西在 Safari 渲染表现与预期(标准)不一致,而且 Safari for Mac 跟 Safari for iOS 的表现还不一定是相同的。
背景
今天遇到了这样一个问题。举个例子,假设外层一个 max-width: 430px 的 section 元素,里面是一个 svg 元素,里面包含动画还有嵌套了一些元素。预期表现是:点击红色区域,绿色背景透明度匀速从 0 切换至 1。
根据所设置的
viewBox="0 0 350 350"
、preserveAspectRatio="xMidYMin meet"
以及width: 100%
,按道理的话,红色的<svg>
及其内嵌套<foreignObject>
和<svg>
,应该都是同等大小的正方形,而且取决于父元素<section>
的宽度。是的,这个在 Chrome 表现没问题,但在 Safari for Mac 上就出现问题了,离奇的是 Safari for iOS 也是正常的。
案例一
如下图,此时
<body>
的宽度是大于 430px,因此<section>
的宽度为 430px,自然<svg>
的宽度就是430px
。但是,当我们点击蓝色框之外,红色区域(截图由于选中元素,该区域表现为橘色)以内的位置,你知道 Safari 定位到的元素是什么吗?
嗯......它定位到
<section>
元素了。意思就是说,内部的 元素区域并未覆盖到点击区,但我宽高明明设置的都是100%
,就很离谱。但是,我在右侧 Elements 选项卡选中
<rect>
元素时,它表现的区域明明就是占满的啊,也就是430 * 430
。Safari 你在玩我?
经多次测试,它可点击区域只有
350 * 350
,也就是viewBox
那个空间。解决办法
由于是 Safari 的 bug,目前只能用一些治标不治本的方法,用魔法打败魔法。
给
<rect>
设置transform: scale(2); transform-origin: left top;
,其父级的<svg>
设置overflow: visible
。由于<foreignObject>
元素默认为overflow: hidden
,因此不用担心点击430 * 430
之外的位置会触发事件。案例二
利用
<svg>
做了一个循环切换的交互,同样地,它在 Chrome 一切安好,而在 Safari 下则惊喜满满。Safari 表现出「忽大忽小」的问题。如下图,灰色背景大小为 430 * 430,而红色背景处则是 350 * 350。
由于录制 GIF 太麻烦了,你可以使用 Safari 打开链接体验一下:https://codepen.io/tofrankie/full/abRWpaE。
解决方法
由于
<foreignObject>
的坑,那就不要嵌套多层,所以可以这样处理,结构上也更清晰。原因
这是 Webkit 的 Bug,相关链接:
该问题早在 2009 年就提出了,至今仍然没有任何进展,隔壁 Chromium 的 Blink 已在 2020 年 9 月修复。其中一个可复现的示例:https://codesandbox.io/s/chrome-foreignobject-defect-wf91j。在 Safari 打开使用
⌘
++
或⌘
+-
去缩放页面就能看到。我用 Chrome 62 亲测了一下,确实也有问题,而且区域更小了。
简言之,根本原因就是 Safari/WebKit 无法正确渲染
<foreignObject>
中的 HTML 元素。实锤了,Safari 就是新时代的 IE 浏览器。
References
The text was updated successfully, but these errors were encountered: