常见的一些兼容性问题
接下来是一些兼容性问题及解决方法的汇总。
Safari 默认不支持 requestIdleCallback
只是默认情况下不支持,用户可以手动打开。(但我们不能要求用户去这么做,所以只能避免使用该 API)
iOS Safari 唤起下载
iOS 端的 Safari 下载 PDF 等可以在浏览器打开的文件时,Safari 更倾向于原地打开,而不是唤起下载。
const iosDownload = url => {
fetch(url)
.then(res => res.blob())
.then(blobRes => {
// 额外套一层blob是为了强制触发下载行为,而不是预览
const blob = new Blob([blobRes]);
const url = URL.createObjectURL(blob);
const aEl = document.createElement('a');
aEl.href = url;
aEl.download = `${title}.pdf`;
aEl.target = '_blank';
document.body.appendChild(aEl);
aEl.click();
document.body.removeChild(aEl);
URL.revokeObjectURL(url);
hideTextTip();
});
};
tailwind 默认使用 is 选择器
tailwind 编译结果含 is 选择器,is 选择器需要浏览器内核版本偏高。会导致旧设备下无样式。
解决方法:安装 postcss-pseudo-is
底部按钮的定位与键盘呼出
按钮固定到屏幕底部是常见的需求,通常 position: fixed; 即可。
但部分安卓设备弹出虚拟键盘时会缩小窗口高度,导致固定底部的按钮跟着上来,使本来就不大的窗口里只剩个按钮了。
解决思路是监听窗口 resize 事件,在窗口缩小和放大时改变按钮的定位。
//按钮的定位 = buttonSticky ? 'sticky' : 'static'
let buttonSticky = false;
//先记录窗口高度
const winHeight = document.documentElement.clientHeight;
window.addEventListener("resize", function () {
//发现窗口高度变小了
if (document.documentElement.clientHeight < winHeight) {
console.log("检测到窗口缩小了,可能是键盘呼出了");
buttonSticky = false;
} else {
console.log("窗口放大了,可能是键盘关闭");
buttonSticky = true;
}
});
微信浏览器与图片保存
微信浏览器 a 标签下载 base64 图片遇到兼容问题,可能无法正常下载。
微信浏览器中,图片下载通常用长按保存图片的方式来实现。
添加到剪贴板的兼容性代码
Clipboard API 对执行环境有两点要求:
浏览器内核版本(Chrome 66+)
安全上下文
所以有了如下的兼容代码:
const setClipboard = (text: string, cb?: () => void) => {
navigator.clipboard
.writeText(text)
.then(() => {
cb?.();
})
.catch((err) => {
console.error("Async: Could not copy text: ", err);
//for compatibility
const input = document.createElement("input");
input.value = text;
input.style.position = "fixed";
input.style.opacity = "0";
document.body.appendChild(input);
input.select();
document.execCommand("copy");
document.body.removeChild(input);
cb?.();
});
};
export default setClipboard;
h5 隐藏滚动条
PC 端的滚动条可以通过以下方式隐藏:
-webkit-scrollbar {
width: 0;
height: 0;
}
但手机端不能。手机端需要通过以下方式隐藏:
但
Safari浏览器似乎无论如何都不能完全隐藏滚动条:
-webkit-scrollbar {
display: none;
}
如果需要显示滚动条可以使用 unset 关键字。
Safari GET 请求丢参数的坑
queryString 参数 不要 携带不符合规范的 "-"。不规范的参数会在 Safari 浏览器直接忽略。
Chrome 在面对这种不规范的 queryString 时会特殊处理,但 Safari 会直接把这部分参数丢掉。
Safari 丢失分割线
苹果设备(iOS/Mac)在渲染很细的分割线时,偶尔的渲染不出来。
这里面分两种情况:
1. 外接屏分辨率较低。
1. 开启了 `px2rem` 来做屏幕适配,`post-css` 把 `1px` 的边框编译成了零点零几 `rem`。
第一种情况除了增粗边框外比较无解。也比较怪异:在 Mac 内建屏幕显示正常,在外接屏幕里就会丢失细节。在两个屏幕之间来回拖动窗口会导致边框时有时无。可能和 Mac 的图形渲染逻辑有关。
第二种情况可以在 post-css 的配置文件里做相关配置,不编译 border 的像素值。
Safari 的 input
最小复现 demo:
import { Input } from "@mui/material";
import { useEffect } from "react";
export default function MyTest() {
useEffect(() => {
document.documentElement.style.fontSize = "4px";
}, []);
return (
<>
raw : <input type="text" className="w-[25rem]" />
mui : <Input className="w-[25rem]"></Input>;
</>
);
}
用 iPhone 的 Safari 打开该页面,input 框的光标会靠左偏移。
可能是因为根元素的字体小于 12px,越小 bug 越明显。所以解决方案就是别让 html 的字体太小。
theme-color
Safari 支持 theme-color,但 Chrome 似乎不支持。
比如,当 Safari 浏览优酷时,整个窗口都会变黑。
微信浏览器下载 PDF
需求是在微信浏览器下载 PDF。
产品所说的下载是指下载到设备本地,而不是自动打开。
安卓端
如果通过 js 下载 blob,然后再通过 a 标签触发下载,在安卓端会提示:'请打开浏览器下载'。但是,在浏览器中地址栏是 blob 地址,无法完成下载。
解决方法:
window.open(url, "_blank");
苹果端
如果在苹果端直接 window.open 则会直接打开 PDF 的预览,而不是所谓下载。
解决方式是通过 js 转 blob 的方式实现下载
解决方法:
fetch(url)
.then((res) => res.blob())
.then((blobRes) => {
// const blob = new Blob([blobRes]);
// 解开这行能在ios_safari触发下载行为 ???
const blob = blobRes;
const url = URL.createObjectURL(blob);
const aEl = document.createElement("a");
aEl.href = url;
aEl.download = `${title}.pdf`;
aEl.target = "_blank";
document.body.appendChild(aEl);
aEl.click();
document.body.removeChild(aEl);
URL.revokeObjectURL(url);
});