Safari浏览器对SVG中的<foreignObject>标签支持不友好,渲染容易错位
在 svg 中需要写一个 markdown 编辑器,需要用到 <foreignObject> 绘制来html,编辑器选择了 simplemde。大致html部分结构如下,<markdown-editor> 组件为定制封装好的 simplemde 编辑器。
<template>
<svg>
<g>
<foreignObject :width="XXX" :height="XXX">
<div xmlns="http://www.w3.org/1999/xhtml">
<markdown-editor></markdown-editor>
</div>
</foreignObject>
</g>
</svg>
</template>
在 Chrome 浏览器开发完成,测试上线都符合预期,但是最后收到用户反馈:她用的是 mac 自带的 Safari 浏览器,在 Safari 里markdown编辑器会出现错位等各种问题。于是我先打开我的 Firefox 浏览器,自测正常,那估计就是 Safari 浏览器的兼容问题了。我看了下 Safari 浏览器的表现:markdown 编辑器每次一打开检查本身的 dom 占位是正确的,但是可视的编辑器界面却会被渲染到最顶部 <svg> 标签的左上角原点(0,0)。最后排查到是因为 safari 对 SVG 中的 <foreignObject> 标签支持不友好,渲染容易错位,特别是遇到 position 属性的时候,而我在引入simplemde 编辑器的同时也引入了 simplemde.min.css,其中大量使用了 position 属性我也在 StackOverflow 和 Github 找到了几篇关于这个bug的讨论帖作为参考:
StackOverflow:SVG foreignObject not working properly on Safari
Github:Safari + foreignobject render issue

最后Github一位程序员ankero一锤定音,原文大意如下:
这不是一个问题,但是可以添加到 README 中。我将在这里添加它,以便如果有人面临类似的问题,可以在这个仓库中找到一个解决方案。在使用这个库(指的是react-d3-tree库,但是遇到的问题是一样的)进行开发时,如果使用 foreignObject 呈现节点,请检查它在 Safari (Mac + iOS)中的显示方式。我们遇到了一个问题,节点内容呈现为父 SVG 的坐标0,0(左上角)。这是由于 Safari 中的一个 bug,它影响 foreignObject 根据顶部 SVG 而不是 foreignObject 本身计算呈现位置。通过检查节点并查看基于浏览器的节点是否在应该在的位置,您可以非常清楚地看到这种效果,但是呈现在了错误的位置。(这段描述和我当时排查的结果一模一样)
那么,如果你看到这个问题,解决方案是什么?
据我所知,如果您使用以下任何 CSS 选项,dom 元素将呈现在错误的位置。所以解决办法就是不要用这些。对我们来说,我们需要检查浏览器是否是 Safari,然后删除一些需要一个或多个这样的样式的功能。
所以不要在 Safari + foreignObject 中使用以下样式:
- position(您可以使用 position: fixed,但这将导致溢出问题)
- webkit-transform-style
- webkit-backface-visibility
- transition
- transform
如何检测 Safari?
我们使用以下片段:
export const IS_SAFARI = /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);
这里提一下 position: fixed 导致的溢出问题,这个在上一个StackOverflow链接中被很多程序员提为解决,方案,这个办法确实能解决一些简单的需求和页面,但是需要注意的一点是,使用这种办法会导致页面缩放出现问题。具体来说就是svg所绘制元素的缩放比例与<foreignObject>所绘制元素的缩放比例不是一致的,这也会带来位置错乱问题。不过可以根据自己的具体情况进行抉择。
各大浏览器之间的兼容问题是各位前端er心中永远的痛,一方面希望谷歌或火狐浏览器能一统江湖,但是另一方面又希望百家齐放能促进前端技术的发展。但是话说又说回来,最重要的还是遵守标准,既然标准都设立在那了,为啥各家不跟上标准呢。
Safari浏览器对SVG中的<foreignObject>标签支持不友好,渲染容易错位的更多相关文章
- WebKit策略:<foreignObject>可用于绘制svg中的html标签,但与<use>搭配不生效
在<svg>里面可以利用<foreignObject>绘制html标签,原本是我在iconfont采用Font class方式引入svg的无奈之举. 起初的设计是所有icon先 ...
- html页面在苹果手机内,safari浏览器,微信中滑动不流畅问题解决方案
1. -webkit-overflow-scrolling:touch是什么? MDN上是这样定义的: -webkit-overflow-scrolling 属性控制元素在移动设备上是否使用滚动回弹效 ...
- Dedecms中{dede:type}标签支持调用父级栏目名称
需求: 我们用{dede:type}标签调用栏目相关内容时,同时需要调用该栏目的父级栏目的名称. {dede:type}标签的代码做了一下开发,支持这个调用了. 开发方法: 1.打开include/t ...
- eclipse中添加jstl标签支持(引入头)
https://blog.csdn.net/wangyuxuan_java/article/details/8580318
- d3.js svg中 g 标签问题一览
svg 中的g标签, 算是比较特殊 1 没有x y属性 2 没有width height 属性 3 不能fill 4 .... g标签基本只管分组问题, 其他功能一概不提供 要解决这些问题, 直接在g ...
- iOS中Safari浏览器select下拉列表文字太长被截断的处理方法
网页中的select下拉列表,文字太长的话在iOS的Safari浏览器里会被自动截断,显示成下面这种: 安卓版的浏览器则没有这个问题. 如何让下拉列表中的文字在iOS的Safari浏览器里显示完整呢? ...
- 利用iOS中Safari浏览器创建伪Web App
在safari浏览器里有一个“添加到主屏幕”选项,我们可以用来创建伪Web App,下面来了解一下iOS中Safari的私有属性 第一步设置Web App的主屏幕图标: 有两种属性值apple-tou ...
- 获取SVG中g标签的宽度高度及位置坐标
1. 问题的出现 对于普通的HTML元素,有很多获得其宽度width.高度height.距左left.距顶top等属性的方法: 类似offsetWidth,clientWidth,width之类的,通 ...
- 发布时一键添加html中的css标签和script标签版本号来防止浏览器缓存
AppendFileVersion 是一个VSIX插件支持vs2015意以上版本 是我用来发布时一键添加html中的css标签和script标签版本号来防止浏览器缓存 分享给大家! download ...
- 解决java web中safari浏览器下载后文件中文乱码问题
解决java web中safari浏览器下载后文件中文乱码问题 String fileName = "测试文件.doc"; String userAgent = request.g ...
随机推荐
- PHP全栈开发(一):CentOS 7 配置LAMP
服务器CentOS7 IP地址:10.28.2.249 进行网络配置 可以使用ip address命令查看当前的网卡状态 两张网卡,一张lo网卡一张ens160网卡 Ens160这个网卡的配置文件为/ ...
- vue2双向绑定原理:深入响应式原理defineProperty、watcher、get、set
响应式是什么?Vue 最独特的特性之一- 就是我们在页面开发时,修改data值的时候,数据.视图页面需要变化的地方变化. 主要使用到哪些方法? 用 Object.defineProperty给watc ...
- [Android开发学iOS系列] 快速上手UIKit
快速上手iOS UIKit UIKit是苹果官方的framework, 其中包含了各种UI组件, window和view, 事件处理, 交互, 动画, 资源管理等基础设施支持. 按照前面的介绍, 用U ...
- Pycharm安装使用
目录 使用pycharm软件 配置调整 下载链接地址:https://www.jetbrains.com/pycharm/download/#section=windows 根据自己的系统需要安装对应 ...
- IDEA中如何导入jar包、IDEA中找不到对应类改怎样解决?(详细图解过程)
今天突然心血来潮.用IDEA运行之前用eclipse编写的项目.发现遇到了一些bug,现在习惯了使用maven管理项目的依赖.一时间忘记了怎样将jar包导入项目中.特此记录一下 文章目录 1.未加入j ...
- 齐博x1客服系统显示客户在哪个页面
如下图所示,要想实现下面的效果,即显示客户给你发消息时,当时处于哪个商品页面.这样方便跟客户针对此商品进行交流. 你的模板如果使用了碎片的话,就可以添加下面的代码index_style/default ...
- flutter系列之:永远不用担心组件溢出的Wrap
目录 简介 Row和Column的困境 Wrap组件详解 总结 简介 我们在flutter中使用能够包含多个child的widget的时候,经常会遇到超出边界范围的情况,尤其是在Column和Row的 ...
- 【MySQL】03_数据类型
MySQL 中的数据类型 类型 类型举例 整数类型 TINYINT.SMALLINT.MEDIUMINT.INT(或INTEGER).BIGINT 浮点类型 FLOAT.DOUBLE 定点数类型 DE ...
- 从ObjectPool到CAS指令
相信最近看过我的文章的朋友对于Microsoft.Extensions.ObjectPool不陌生:复用.池化是在很多高性能场景的优化技巧,它能减少内存占用率.降低GC频率.提升系统TPS和降低请求时 ...
- 安装 TypeScript 并编译成JS
官网: https://github.com/microsoft/TypeScript TypeScript是一种由微软开发的开源.跨平台的编程语言.它是JavaScript的超集,最终会被编译为Ja ...