返回文章列表

常见的一些兼容性问题

接下来是一些兼容性问题及解决方法的汇总。

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 对执行环境有两点要求:

  1. 浏览器内核版本(Chrome 66+)

  2. 安全上下文

所以有了如下的兼容代码:

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 的像素值。

Safariinput

最小复现 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>;
    </>
  );
}

iPhoneSafari 打开该页面,input 框的光标会靠左偏移。

可能是因为根元素的字体小于 12px,越小 bug 越明显。所以解决方案就是别让 html 的字体太小。

theme-color

Safari 支持 theme-color,但 Chrome 似乎不支持。

比如,当 Safari 浏览优酷时,整个窗口都会变黑。

微信浏览器下载 PDF

需求是在微信浏览器下载 PDF

产品所说的下载是指下载到设备本地,而不是自动打开。

安卓端

如果通过 js 下载 blob,然后再通过 a 标签触发下载,在安卓端会提示:'请打开浏览器下载'。但是,在浏览器中地址栏是 blob 地址,无法完成下载。
解决方法:

window.open(url, "_blank");

苹果端

如果在苹果端直接 window.open 则会直接打开 PDF 的预览,而不是所谓下载。
解决方式是通过 jsblob 的方式实现下载
解决方法:

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);
  });