BlackGlory / appoint-font

🌳 The easiest font setting extension.
https://chrome.google.com/webstore/detail/lmjdabbpgabigbonekfpjhfgjekpnkge
MIT License
63 stars 5 forks source link

请问下为什么不支持web font? #24

Open prismriverrr opened 3 months ago

prismriverrr commented 3 months ago

我在用这个插件前,是用stylus写font-face规则的,web font也是能替换的。

或者后续可否考虑添加一项设置,让用户自行选择是否替换web font。

BlackGlory commented 3 months ago

我有一段时间没有处理字体相关的东西了, 但我没记错的话, Web字体的font-family是在编写代码时自定义的, 因此一个web字体可以有无数种不同的名字.

为了替换这类字体, 扩展需要在每次加载页面后, 获取页面加载的字体清单, 这很可能会导致相应字体的替换时间点过晚. 考虑到字体是可以动态加载的, 这也会导致扩展程序需要在每个页面注入脚本以监视字体加载, 这会降低使用电池的设备的续航能力.

另一方面, 本扩展程序将字体统一划分为"标准"和"等宽"两种, 没有办法事先知晓Web字体属于哪一种, 需要执行分析. 字体分析实际上非常占用CPU时间, 这会显著降低使用电池的设备的续航能力.

此外, 如果一个网页的设计者已经考虑使用Web字体(尤其是中文Web字体, 文件体积通常很大, 会明显影响页面的加载), 那么使用Web字体很可能是有意义的, 有必要尊重这些页面的设计.

prismriverrr commented 2 months ago

那如果本地已经安装了对应的web字体,是会按照设定的规则发生替换吗?我不太理解readme的描述,经过我实测,font-family里的web字体安装在本地之后,网页字体显示并未发生任何变化。

This extension will not break web fonts, unless the corresponding web font is already installed locally.

BlackGlory commented 2 months ago

那如果本地已经安装了对应的web字体,是会按照设定的规则发生替换吗?我不太理解readme的描述,经过我实测,font-family里的web字体安装在本地之后,网页字体显示并未发生任何变化。

This extension will not break web fonts, unless the corresponding web font is already installed locally.

安装新字体后:

如果以上都排除, 那么问题可能与font-face规则的顺序有关. 浏览器在加载CSS样式表时会从最后一条font-face规则开始加载字体, 向上寻找fallback. 如果扩展程序的规则注入得太早, 可能导致采用页面自身的规则. 不幸的是, 扩展程序使用的方法很难精确控制注入的时间点, 所以过早或过晚注入都是有可能的.

BlackGlory commented 2 months ago

另外就是浏览器本身也有一些奇葩的问题, 比如https://stackoverflow.com/q/68437455/5462167, 也不知道现在修复了没有.

prismriverrr commented 2 months ago

如果以上都排除, 那么问题可能与font-face规则的顺序有关.

可否分析下这个网址的情形,以正文第一段为例,用的字体是Inter,我本地有安装,但并未替换成Arial。

image

BlackGlory commented 2 months ago

我看了一下, 这个还挺奇怪的, 即使我把注入CSS的时间点推迟5秒, 页面渲染的也是Web字体.

而且Web字体在document.fonts里也总排在最后, 也许Chrome有了新的行为? image

BlackGlory commented 2 months ago

我知道原因了, 页面的font-face的优先级太高了.

image

@font-face {
    font-display: swap;
    font-family: Inter;
    font-stretch: 75% 100%;
    font-style: oblique 0deg 20deg;
    font-weight: 1 999;
    src: url(/static/media/Inter.var.c2fe3cb2b7c746f7966a.woff2) format("woff2 supports variations"),url(/static/media/Inter.var.c2fe3cb2b7c746f7966a.woff2) format("woff2-variations")
}

如果注入改成这样(需要用eternity加载)就可以替换:

// @name Test
// @match https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face
import { addStyleSheet } from 'https://esm.sh/userstyle@0.2.1'

console.log('Injected')

addStyleSheet(`
  @font-face {
    font-display: swap;
    font-family: Inter;
    font-stretch: 75% 100%;
    font-style: oblique 0deg 20deg;
    font-weight: 1 999;
    src: local("Noto Serif CJK SC");
  }
`)

这三行, 少了任何一行, 自定义font-face规则都无法顶替掉页面的font-face规则.

    font-stretch: 75% 100%;
    font-style: oblique 0deg 20deg;
    font-weight: 1 999;
BlackGlory commented 2 months ago

在上一条提到的CSS里, font-weight: 400;(页面选择的字重), font-weight: 1 1000;(理论字重范围), font-weight: 1 998;(比页面的字重范围更小)都不能覆盖页面的font-face规则, 只有font-weight: 1 999;可以做到.

我认为除非扩展程序转为读取页面上的Web字体, 并为此创建专门的替换规则, 否则想要覆盖掉这些规则是不可能的.