如何在 CSS 过渡期间防止 Webkit 文本呈现变化

Posted

技术标签:

【中文标题】如何在 CSS 过渡期间防止 Webkit 文本呈现变化【英文标题】:How to prevent Webkit text rendering change during CSS transition 【发布时间】:2012-09-12 04:56:41 【问题描述】:

我正在使用 CSS 转换来转换 CSS 转换状态(基本上是转换元素的比例)。我注意到当元素转换时,页面上的其余文本(在 Webkit 中)往往会稍微改变其呈现,直到转换完成。

小提琴:http://jsfiddle.net/russelluresti/UeNFK/

我还注意到这不会发生在我的标题上,它们上有 -webkit-font-smoothing: antialiased 属性/值对。所以,我想知道,有没有办法让文本保持其默认外观(字体平滑的“自动”值)并且在过渡期间不改变渲染。

我已尝试将文本显式设置为使用“自动”值,但这无济于事。我还应该注意,将 font-smoothing 设置为“none”也可以防止在过渡期间呈现闪烁。

感谢任何帮助。

编辑 1

我应该注意到我使用的是 OS X。在 Parallels 上查看我在 Chrome 中的测试时,我没有看到两个不同的段落表现不同,因此这可能是 Mac 独有的问题。

【问题讨论】:

21。 Safari 版本是 6。它发生在两个浏览器中,这让我认为它是 Webkit,而不是浏览器。 抗锯齿和别名段落都表现出相同的行为。 chrome 版本 23.0.1270.0 金丝雀 | 21.0.1180.89 米 | 5.17 狩猎 我猜你正在使用 Chrome 的开发版本。不过,操作系统可能在其中发挥了作用。我将编辑问题以说明我使用的是 OSX。 我完全不知道为什么会这样,但是添加 '-webkit-transform: translateZ(0);' to '.antialiased 似乎可以解决它。如果你将它添加到'p ',它甚至可以工作。由于我无法解释为什么这样做有效,因此将其作为答案提供给我感觉不对。希望有帮助! @Christofer 这使它们保持一致 - 但它使它们都显示为抗锯齿(它们都是更薄的文本)。我正在尝试使未消除锯齿的文本(第一段)保持其默认样式(看起来比消除锯齿的文本更粗)。 【参考方案1】:

我想我找到了解决办法:

-webkit-transform: translateZ(0px);

在父元素上强制硬件加速似乎可以解决问题...

编辑 如评论所述,此 hack 会禁用字体平滑,并会根据您的字体、浏览器和操作系统降低文本渲染!

【讨论】:

尝试了字体平滑,但没有成功。试过了,效果很好 这并没有给我所声明的问题所需的结果,但这有助于解决我遇到的其他 CSS 过渡问题(例如在过渡元素中隐藏/显示内容时奇怪的闪烁文本)。 对我不起作用,而 -webkit-font-smoothing:antialiased;和 -webkit-backface-visibility:hidden;作品。学分在这里***.com/questions/11589985/… +1 太棒了,这是我发现自己遇到的情况的唯一方法 这首先会禁用字体平滑。所以你在过渡开始时没有字体平滑,在过渡时没有字体平滑,最后没有字体平滑。所以没有字体平滑变化,也没有字体平滑。【参考方案2】:

2020 年 8 月更新

您不再需要使用媒体查询来定位 Safari 以启用亚像素字体平滑。默认就可以了。

然而,虽然它默认使用亚像素字体平滑,但 Chrome 的字体平滑有一个显着的美中不足,对于任何想看的人来说一致的文本呈现

    这是 Chrome 在深色背景上对浅色文本的渲染 这是 Chrome 在浅色背景上对深色文本的渲染

看上面字母e的整体大小。深色背景上的浅色文本比浅色背景上的深色文本明显更重(具有相同的 css 字体样式)。

对于尊重用户的深色/浅色主题设置的网站,一种解决方案是使用限制为深色模式的媒体查询定位 Chrome,并将其切换为非亚像素平滑,如下所示:

@media screen
and (-webkit-min-device-pixel-ratio: 0)
and (min-resolution: 0.001dpcm)
and (prefers-color-scheme: dark) 
  body 
    -webkit-font-smoothing: antialiased;
  

结果:

无论是在深色上渲染还是在浅色上渲染深色,文本粗细都更加一致。

查看前后的并排比较:

--

2018 年 5 月更新

-webkit-font-smoothing: subpixel-antialiased 现在在 Chrome 中没有效果,但在 Safari 中它仍然有很大的改进,但仅限于 RETINA。没有它,在视网膜屏幕上的 Safari 中,文本会变得单薄而乏味,而有了它,文本就会有适当的权重。但是如果你在 Safari 中的非视网膜显示器上使用它,(尤其是在轻量值下)文本是一场灾难。强烈推荐使用媒体查询:

@media screen and (-webkit-min-device-pixel-ratio: 2) 
  body 
    -webkit-font-smoothing: subpixel-antialiased;
  


如果您希望至少部分避免较薄的抗锯齿文本,则显式设置 -webkit-font-smoothing: subpixel-antialiased 是当前最佳解决方案。

--tl;博士--

对于默认字体渲染使用亚像素抗锯齿的 Safari 和 Chrome,任何强制基于 GPU 渲染的 CSS(如上面使用 translateZ 使用变换甚至只是缩放转换的建议)都会导致 Safari 和 Chrome 自动“放弃”子像素抗锯齿字体平滑,而改用抗锯齿文本,它看起来更轻更薄,尤其是在 Safari 上。

其他响应集中在通过简单地设置或强制字体平滑到较薄的抗锯齿文本来保持恒定的渲染。在我看来,使用 translateZ 或 backface hidden 会显着降低文本渲染的质量,如果您希望文本保持一致并且您可以使用较薄的文本,那么最好的解决方案就是使用 -webkit-font-smoothing: antialiased。但是,显式设置 -webkit-font-smoothing: subpixel-antialiased 实际上确实有一些效果 - 文本仍然略有变化,并且在 GPU 上呈现的过渡期间明显变薄,但没有此设置时没有那么薄。所以看起来这至少部分地阻止了切换到直接抗锯齿文本。

【讨论】:

感谢您的精彩文章! 这是最好的解决方案。所有其他人都会降低文本渲染,这是 OP 特别要求 避免 我的救命稻草!谢谢。避免在 css 转换后突然切换到子像素渲染。至少在不透明度过渡的情况下,即使在过渡期间,它也会使字体保持在(理论上总是默认的)子像素渲染上。太好了! 最适合我们的解决方案!谢谢 谢谢,我在一年多前就遇到过这个问题,然后就忘记了。这是为我解决所描述问题的唯一解决方案。【参考方案3】:

我注意到几乎每次由于转换而出现图形问题(闪烁/卡顿/断断续续/等)时,使用 -webkit-backface-visibility: hidden;在起作用的元素上往往会解决问题。

【讨论】:

这是(当前)正确答案。据我所知,webkit-font-smoothing 不久前被删除,应该再次添加,但目前在最新版本的 Chrome 中对我不起作用。 translateZ 技巧似乎也不再起作用了。我想这可能随时再次改变。 :// 这导致我的一些文字变得模糊。【参考方案4】:

要防止由于硬件加速导致文本呈现变化,您可以:

    将所有文本设置为 -webkit-font-smoothing:抗锯齿。这意味着文本更细且没有亚像素抗锯齿。

    如果您希望对受硬件加速影响的文本进行亚像素抗锯齿(字体平滑的默认类型),则将该文本放入输入中,不带边框并禁用,将保留该子像素-像素抗锯齿(至少在 Mac OS X 上的 Chrome 上)。我没有在其他平台上测试过,但是如果亚像素抗锯齿很重要,你至少可以使用这个技巧。

【讨论】:

我已经在 Win8.1 和 Chrome 47 上测试了选项 2(输入元素的技巧),但它不起作用。【参考方案5】:

如果您在 Mac 上使用 Firefox,则需要使用以下 css 来解决此问题。

-moz-osx-font-smoothing: grayscale;

更多信息请访问Webfont Smoothing and Antialiasing in Firefox and Opera

【讨论】:

【参考方案6】:

这对我有用。希望能帮助到你。在其他 *** 帖子中找到。

-webkit-font-smoothing:antialiased;
-webkit-backface-visibility:hidden;

【讨论】:

【参考方案7】:

为防止渲染更改,您需要设置font-smoothing: antialiased(或none)。

浏览器禁用亚像素字体渲染可能是硬件加速的副作用。当您渲染的背景不断变化时,文本不能在单独的图层上渲染,因为必须检查每一帧与所有背景图层。这可能会严重降低性能。

Apple 经常在 their own 网站上禁用亚像素字体平滑。

【讨论】:

将字体平滑设置为抗锯齿的问题是文本看起来不像我想要的那样。我想要将字体平滑设置为“自动”(更大胆的外观)的视觉效果 - 但是当你这样做时,文本会在任何过渡期间发生变化。所以,我的目标是始终保持“自动”的大胆外观。 您可以通过不使用硬件加速来解决它。在 jQuery 中使用计时器并手动进行转换(没有 CSS 转换)。我不确定我是否会推荐它,因为性能和流畅度会更差。 是的,我可以使用 jQuery 对其进行动画处理...如果没有其他解决方案,这可能是唯一的解决方案。【参考方案8】:

除了上述解决方案(元素上的-webkit-transform: translateZ(0px) 和页面上的-webkit-font-smoothing: antialiased)之外,某些元素可能仍然表现不佳。对我来说,它是输入元素中的占位符文本:为此,请使用 position:relative

【讨论】:

【参考方案9】:

我遇到了同样的问题。仔细阅读:

我注意到当元素过渡时,文本的其余部分 在页面上(在 Webkit 中)往往会稍微改变其呈现,直到 过渡完成。

上述解决方案似乎都不起作用。但是,设置(类似的东西)

#myanimation  -webkit-transform: translateZ(0px); 

有动画确实有效的元素上。

通过将动画元素带到 GPU 层,您可以将其脱离页面渲染的正常流程(例如,z-index 之类的东西也不再起作用)。作为副作用,动画和页面的其余部分将不再相互影响。

如果它影响你的字体渲染,当然它只会影响动画元素。我在我的 Chrome 中看不出有什么不同。

【讨论】:

我的立场是正确的。我确实在页面的其余部分看到了字体渲染的变化,在没有应用 translateZ(0) 的地方也是如此。 当我的字体图标变得模糊时,这是唯一对我有用的方法。将变换应用于正在动画的部分,它解决了问题。 老兄,这已经在 2 年前回答了。就在上面...完全相同的答案/代码。 是的,我唯一的一点是您必须将-webkit-transform 放在具有动画的元素上,以防止在页面上的其他元素上进行渲染更改 。但正如评论的那样,它工作了一段时间,当我稍后更改页面的位时停止工作。

以上是关于如何在 CSS 过渡期间防止 Webkit 文本呈现变化的主要内容,如果未能解决你的问题,请参考以下文章

过渡期间文本变得模糊

如何防止用户使用 CSS 复制某个 div 的文本?

Webkit 浏览器中的 CSS 过渡填充故障

如何在悬停过渡期间使文本翻译/宽度增加

CSS Webkit颜色过渡循环

webkit 过渡在 Mozilla 和 Opera 中结束?