在Chrome中使用CSS transform: scale();后文本变得模糊。

178

最近Google Chrome进行了更新,似乎在执行transform: scale()之后会导致文本模糊。具体来说,我正在执行以下操作:

@-webkit-keyframes bounceIn {
  0% {
    opacity: 0;
    -webkit-transform: scale(.3);
  }

  50% {
    opacity: 1;
    -webkit-transform: scale(1.05);
  }

  70% {
    -webkit-transform: scale(.9);
  }

  100% {
    -webkit-transform: scale(1);
  }
}

如果您在Chrome中访问http://rourkery.com,您应该会看到主文本区域上的问题。它以前不会这样做,似乎也不会影响其他Webkit浏览器(如Safari)。有一些其他帖子提到人们遇到了类似于3D变换的问题,但找不到任何关于2D变换的信息。
非常感谢您的任何想法!

刚刚使用Firefox和IE 10访问了该网站,没有发现问题。如果问题只出现在Chrome上,你可能需要等待谷歌自己修复。 - Nolonar
我之前也遇到过这个问题,正如Nolonar所提到的,我们必须等待Google修复它。 - raj_n
不是解决方案,但我注意到问题只会在我使用CSS optimizeLegibility时发生。 - Bangkokian
链接已损坏。 - Timothy003
任何遭受模糊文本困扰的人都应该阅读保罗·刘易斯(Paul Lewis)的这篇旧文章。简而言之,主要关于次像素抗锯齿的怪癖。文章链接:https://www.html5rocks.com/en/tutorials/internals/antialiasing-101/ - dziku86
38个回答

116

我遇到过这个问题很多次,似乎有两种方法可以解决它(如下)。您可以使用这些属性中的任何一个来修复渲染问题,或同时使用两者。

将背面可见性隐藏可以解决问题,因为它将动画简化为对象的正面,而默认状态是正面和反面。

backface-visibility: hidden;

TranslateZ同样有效,因为它是一种将硬件加速添加到动画中的技巧。

transform: translateZ(0);

这两个属性都可以解决您遇到的问题,但有些人还喜欢添加

-webkit-font-smoothing: subpixel-antialiased;

针对他们的动画对象。我发现这可以改变网络字体的渲染,但请随意尝试该方法。


18
这些技术似乎都能改善情况,但我仍无法让Chrome在清晰度方面达到我在Firefox中看到的水平。 - Michael Martin-Smucker
15
backface-visibility: hidden;在我的情况下确实解决了一些由不透明度过渡引起的奇怪模糊动作问题。现在,这种奇怪的动作已经消失了,但它使得我div中的文本永久模糊了。 - ITWitch
18
正如 @ykadaru 建议的那样,在你的 transform: 代码中添加 perspective(1px),这对我在 Chrome 中起了作用,而其他方法都没有解决问题。 - Serge Eremeev
4
无法在 Chrome 版本 65.0.3325.162 (官方版本) (64 位) 上运行,该 Chrome 运行在 Ubuntu 17.10 并使用 Gnome X11 会话(Wayland 关闭) 。 - Marecky
3
在Chrome 72中,前两个选项会导致文本在变换期间和结束时模糊。 - brandito
显示剩余4条评论

55

尝试了这里所有其他方法后,最终解决了我的问题是删除will-change:transform;属性。出于某种原因,它导致Chrome中可怕的模糊缩放效果,但在Firefox中没有。


7
为什么会有人踩这个?我不太明白... :( 在某些版本的Chrome中,这是一个完全有效的问题,而且似乎“will-change”总体上仍然很新,可能不应该使用。有关更多信息,请参见https://greensock.com/will-change - Dan
遇到了同样的问题。感谢您的发布。 - raine
2
我在Chrome 75上使用material-design-components时遇到了相同的问题。删除“will-changed”CSS样式解决了这个问题。 - Rob
7
我有相反的问题,添加 will-change: transform; 能稍微修复这个问题。 - Jakub Zawiślak
1
这很奇怪。因为解决方案中的解决方法对我的简单关键帧动画无效,但实际上解决了模糊的结果。@keyframes heart-pulse { from { transform: scale(0); opacity: 1; } 25% { transform: scale(1.15); } 50% { transform: scale(1); } 75% { transform: scale(1.15); } to { transform: scale(1); opacity: 1; } } - vaxul
显示剩余4条评论

33

为了改善模糊现象,特别是在Chrome浏览器上,尝试按照以下步骤操作:

transform: perspective(1px) translateZ(0);
backface-visibility: hidden;

透视可以在用户和z平面之间增加距离,从技术上来说它会缩放对象,使得模糊看起来更像是“永久”的。上面的perspective(1px)就像鸭子胶带一样,因为我们正在匹配我们试图解决的模糊问题。你可以尝试使用以下css以获得更好的效果:

transform: translateZ(0);
backface-visibility: hidden;

7
对我来说,这实际上让情况变得更糟。 - balu
1
对我来说,这个修复了故障(没有它,在动画完成后元素会移动1像素,而transform: perspective(1px)可以解决这个问题!) - Sergiu
@balu,请检查我的更新答案!去掉 perspective(1px) 属性,看看效果是否更好。 - ykadaru
你的回答与问题代码完全相同。 - Jorge Fuentes González

23

我发现调整缩放比例略微有所帮助。

使用scale(1.048)而不是(1.05)似乎可以更好地近似到整像素字体大小,减少子像素模糊。

此外,我还使用了translateZ(0),这似乎可以调整Chrome在变换动画中的最终舍入步骤。对于我的onhover用法来说,这是一个加号,因为它提高了速度并降低了视觉噪音。然而,对于一个onclick函数来说,我不会使用它,因为变换后的字体看起来不是那么清晰。


3
这是我唯一有效的方法。其他方法(如backface-visibility、添加滤镜、透视和传统的translateZ)只会使情况变得更糟。尝试缩放到整个像素。例如,使用1.1429(16/14)的比例因子,将字体大小从14px增加到16px。 - hugo der hungrige
3
没有使用translateZ(0)也能为我工作,只需将“1.05”更改为“1.048”。 - A. Volg

19

与其

transform: scale(1.5);
使用。
zoom : 150%;

修复了Chrome中文本模糊的问题。


1
它可以帮助,但也会引入其他问题,比如有时会出现白色边框线。 - Kevin
2
不确定为什么会被踩。当我将其应用于复选框时,它比transform:scale()效果要好得多。 - Brian McCall
3
对于Firefox浏览器,使用"transform: scale()"属性可以完美地实现缩放效果,而不会出现模糊的情况。你需要检测浏览器类型,并对Chrome/Safari和Firefox分别进行处理。 - Naisheel Verdhan
21
另一个问题是 Zoom 似乎不能与转换属性一起使用,因此无法用于 CSS 动画。 - ericgrosse
3
它起作用并修复了模糊的问题,但它也改变了元素的位置。 - user1156544
显示剩余5条评论

11

这一定是Chrome(版本56.0.2924.87)的一个bug,但以下方法在控制台中改变CSS属性时消除了模糊。我会报告此问题。

filter: blur(.0px)

1
你的错误报告有进展了吗? - Diazole
抱歉,我甚至不记得我提交了错误报告的位置。但我确实提交了。 - andyw
我正在使用Bootstrap(4.4.1),Chrome(80.0.3987.132),Windows 10(视图缩放125%),并且我的下拉菜单中有模糊的文本。菜单是使用transform:translate3d();定位的,这似乎引起了问题。建议的解决方案都没有对我起作用,除了/有点像这个。只有当我首先将其设置为某个正值(例如blur(0.1px))然后更改为blur(0px)时,它才起作用。由于元素是动态的,并且需要动态(JS)解决方案,...这很糟糕:\ - akinuri

8

1
这在 Windows 上的 Firefox 85 中“解决”了问题,并在 Chrome 88 中有所改善,但并未完全解决...另外,遗憾的是,你不能真正自由地使用它。 - MrSegFaulty

8

Sunderls 帮助我找到了答案。除了 filter: scale 不存在,但是 filter: blur 存在。

将下面的声明应用于出现模糊的元素(在我的情况下它们位于一个转换的元素内):

backface-visibility: hidden;    
-webkit-filter: blur(0);

它几乎完美地工作了。 "几乎" 是因为我使用了一个过渡效果,当在过渡中时,元素看起来不完美,但一旦过渡完成,它们就会变得完美。


只有 -webkit-filter: blur(0); 对我有效。当我之后重置缩放时,backface-visibility: hidden; 会使我的元素模糊。 - Kai Hartmann
这对于Chrome来说有点有趣...如果我设置blur(0px);它并不能解决问题。但是如果我设置blur(1px);,然后按下向下箭头键到blur(0px);,它看起来就正确了。无论我在CSS中写什么,在页面刷新后都会消失。 - Tom Roggero
1
@TomRoggero 这个问题似乎不太关于模糊属性值,而更多是关于何时进行布局重新绘制。您可以尝试在一定延迟后使用JavaScript强制重新绘制元素并观察结果。 - Gajus
-webkit-filter: blur(0); transform: perspective(1px) translateY(0) translateZ(0); 这些修复了我的问题。 - undefined

7
我发现,任何相对变换都会出现问题。translateX(50%),scale(1.1)或其他相对值都会导致模糊的文本/图像。提供绝对值总是有效的(不会产生模糊的文本/图像)。在这里提到的解决方案都没有起作用,我认为还没有解决方法(我正在使用Chrome 62.0.3202.94写这篇文章)。在我的情况下,transform: translateY(-50%)translateX(-50%)引起了模糊(我想居中一个对话框)。为了达到更加“绝对”的值,我必须将小数值设置为transform: translateY(-50.09%)translateX(-50.09%)。注意:我相当确定这些值在不同的屏幕尺寸上会有所变化。我只是想分享一下我的经验,如果它能帮助某个人。

1
我在做完全相同的事情时遇到了完全相同的问题。我正在使用translate3d(-50%,-50%,0)居中模态。在我的情况下,我将值增加到-50.048%,看起来完美无瑕。 - Chris Gutierrez

7
在我的情况下,以下代码导致字体模糊:
-webkit-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);

只需添加缩放属性,问题就得到解决了。尝试调整缩放比例,以下是对我有效的设置:

zoom: 97%;   

5
Firefox不支持“zoom”。 - Dustin Poissant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接