Et tu, Grammarly?

订阅 博客 RSS feed 笔记 RSS feed 并关注 Mastodon Bluesky

2025年3月29日,星期六

近几个月来,我陆续收到一些报告,说我的网站坏了。他们说布局歪了,东西的尺寸也很奇怪。他们还提供了屏幕截图来证明。这对于一个专业的网站构建者来说是很尴尬的。

值得庆幸的是,我的受众精通技术,并且发现罪魁祸首是 Grammarly browser extension。安装了这个扩展程序后,我的网站就坏了,就这么简单。我最初的反应是:“抱歉,是他们的 bug,不是我的”。但在收到太多报告后,我不得不注册并亲自安装了 Grammarly(感谢临时邮箱)。

发现

在接受了 Grammarly Firefox (Mullvad browser) 扩展程序的所有权限后:

我很快找到了证据。Grammarly 将一个样式表注入到网页中 (这是一个 GitHub Gist)。这个样式表是从本地扩展程序的资源加载的。网页本身无法使用 StyleSheetList 找到它。它甚至绕过了 Content Security Policy。它实际上是一个隐形的样式表,网站本身无法检测到。至少在 Firefox 中是这样,我没有兴趣在其他浏览器中安装 Grammarly。

Grammarly 扩展程序还在 <html> 文档中添加了一个自定义的 <grammarly-desktop-integration> 元素。无论您是否与扩展程序交互,这都会发生在每个网站上(我不知道它有什么用)。

为什么是我?

Grammarly 的样式表 的末尾,您会发现以下 CSS:

:host,
:root{
--rem:16
}

除了省略分号的明显错误之外,这似乎是无害的。您可能知道神奇数字 16。默认情况下,在 CSS 单位中 1rem = 16px(有点复杂)。更进一步,Grammarly 正在进行某种形式的动态字体大小调整:

.kE2Bj{
font-size:calc(0.86px*(var(--rem)-2));
line-height:calc(1.2868px*(var(--rem)-2));
}

此代码是自动生成的,因此不太清楚发生了什么。我以为他们可能会使用浏览器的基本字体大小动态设置 --rem 值——这对可访问性有好处——但经过测试,情况并非如此。也许该扩展程序有自己的设置?

顺便提一下,Grammarly 还在加载 Inter font 的二十个变体——Four Naan, Jeremy? That’s Insane!——Inter 可以作为 variable font 使用。你不需要二十个单独的 @font-face 规则,~~Jeremy~~ Grammarly。

无论如何,碰巧我也在使用 --rem 自定义属性名称。我正在尝试自己的 fluid typography 实验性风格:

@layerbase{
:root{
--rem:0.0625rem;
--fluid:calc((100vi-(400*var(--rem)))/(1920-400));
--font-size-h1:clamp(
calc(31*var(--rem)),
calc((31*var(--rem))+(80-31)*var(--fluid)),
calc(80*var(--rem))
);
}
}

它的工作原理是另一篇博客文章的主题。

重要的是,我正在使用 --rem,并且它是在 cascade layer 中定义的。图层之外的样式优先于图层内的样式,无论 CSS 特性如何(这是一个需要一本书才能讲完的主题)。源顺序也很重要,因此 Grammarly 的 --rem 无论如何都可能获胜。

TL;DR: Grammarly 打破了我的计算,从而破坏了我的网站。

解决方案 🤡

最初 我使用了一个 mutation observer 来检测附加的 Web 组件,并添加额外的 !important 样式来夺回我的领地。一旦我了解了确切的问题,我就将我的自定义属性更改为 --🤡,这是 完全有效的

基本上,名称 --rem 现在被认为是“有害的”,因为 Grammarly 是糟糕的 Web 市民。他们正在生成随机类名,为什么专门劫持 --rem?为什么要将其全局应用于 :root?他们也可以,你知道,不要将他们的代码注入到每个网页,除非实际使用了该扩展程序?

我已经联系了 Grammarly 支持。他们很快做出了回应,但我尚未联系到了解我问题的技术人员。我希望我们可以交换名称。Grammarly 可以为他们的罪行使用 --🤡,其余的人可以使用 --rem。你们这些书呆子有人在 Grammarly 工作吗?让我们实现它。