CSS过渡效果会导致图像模糊/在Chrome中将图像移动1px?


150

我有一些CSS,悬停时CSS过渡效果会移动div。

正如您在示例中看到的那样,问题在于translate过渡具有可怕的副作用,即使div中的图像向下/向右移动1px(并且可能会略微调整大小吗?),以至于它看起来不合适并没重点...

毛刺似乎一直在应用悬停效果的整个过程中,并且从反复试验的过程中,我可以肯定地说,似乎仅在平移过渡移动div时才出现(框阴影和不透明度也适用,但对删除后的错误)。

仅当页面具有滚动条时,才会出现该问题。因此,仅使用一个div实例的示例就可以了,但是一旦添加了更多相同的div,并且页面因此需要滚动条,问题就会再次出现。


1
我在OSX上使用Chrome 27,这很好。我相信,将内容放到图层中时,它会在动画过程中变成位图,而在旧版本/旧显卡上,这看起来并不好。尝试使用较新的版本,看看是否已修复。
Rich Bradshaw

Chrome 25 OS X上的一切都很好。顺便说一句:我建议为背景渐变纹理使用不同于300KB图像的方法!
Paolo

感谢@Paolo-背景图像仅用于演示,不是实际站点中使用的图像!
刘易斯

2
当动画由GPU处理时,问题就出现了,看起来位图舍入有点差了。转载于加纳利,但如果关闭GPU加速它工作正常
丘壑

您可以尝试每帧使用此解决方案... stackoverflow.com/a/42256897/1834212
Miguel

Answers:


247

2020年更新

  • 如果图像模糊,请务必从下面检查答案,尤其是image-renderingCSS属性。
  • 为了获得最佳实践的可访问性和SEO,您可以<img>使用对象适合 CSS属性用标签替换背景图片。

原始答案

试试这个 CSS中

.your-class-name {
    /* ... */
    -webkit-backface-visibility: hidden;
    -webkit-transform: translateZ(0) scale(1.0, 1.0);
}

这样做是为了使该分区表现为“更多2D”。

  • 默认情况下绘制背面,以允许通过旋转等翻转事物。如果只向左,向右,向上,向下,缩放或顺时针旋转,则无需这样做。
  • 将Z轴平移为始终具有零值。
  • Chrome现在可以处理backface-visibility并且transform没有-webkit-前缀。我目前不知道这会如何影响其他浏览器的渲染(FF,IE),因此请谨慎使用非前缀版本。

27
可能什么也没解释,但足以为我解决此问题。
McNab

@Class Stacker-要解释什么?您只需将代码复制粘贴到有问题的元素。顺便说一句,这很好用!
easwee

1
我建议此解决方案stackoverflow.com/a/42256897/1834212 im发布链接以避免重复的链接
Miguel

1
有人可以确认它是否仍然有效,因为每当我添加`-webkit-backface-visibility`和时-webkit-transform,当打开chromes开发者控制台时,我看不到任何更改。我看到这两个css属性被遍历了,就好像它们被覆盖了一样,但是没有(空css和html)。好像Chrome不再接受它们。
凯文M

1
@KevinM尝试不使用-webkit-前缀,这些现在是标准CSS。
sampoh

91

您需要对元素应用3d变换,因此它将获得自己的复合层。例如:

.element{
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
}

要么

.element{
    -webkit-transform: translate3d(0,0,0);
    transform: translate3d(0,0,0);
}

有关图层创建条件的更多信息,请点击此处阅读:Chrome中的加速渲染


一个解释:

示例(悬停绿色框):

当您在元素上使用任何过渡时,它会导致浏览器重新计算样式,然后即使过渡属性是可见的(在我的示例中是不透明的),也要重新布局内容并最终绘制一个元素:

屏幕截图

这里的问题是内容的重新布局,当过渡发生时,该内容可以使页面上的“跳舞”或“闪烁”元素产生效果。如果要进行设置,请选中“显示复合层”复选框,然后将3d变换应用于元素,您将看到它获得了自己的层,并用橙色边框勾勒了轮廓。

屏幕截图

元素获得自己的图层后,浏览器只需要在过渡时合成图层即可,而无需重新布局甚至进行涂装操作,因此必须解决以下问题:

屏幕截图


好东西!明确指出您的答案有多详细!您使用哪种软件进行屏幕捕获/箭头定位?
kroe 2013年

当场交友!在那里省了我很多麻烦。

这对我有用。刚开始,我在要设置动画的父级上使用translateZ,但是其中的背景图像精灵仍然模糊。我正在使用Velocity.js缩放其中的另一个容器,并应用了类似translateZ: 0.000001(一些infinitesimal#)和瞧!再次锐化背景图像!
notacouch 2015年

谢了哥们。这解决了我的问题。顺便说一句,我的问题是我有一个旋转90度的元素,并具有使用不透明度的淡入过渡。触发转换时,元素的内容从左移动1px。
劳埃德·亚伦

42

嵌入的YouTube iframe也存在相同的问题(翻译用于将iframe元素居中)。在尝试之前,以上解决方案均无效重置CSS过滤器无效和进行魔术操作。

结构体:

<div class="translate">
     <iframe/>
</div>

风格[之前]

.translate {
  transform: translateX(-50%);
  -webkit-transform: translateX(-50%);
}

风格[之后]

.translate {
  transform: translateX(-50%);
  -webkit-transform: translateX(-50%);
  filter: blur(0);
  -webkit-filter: blur(0);
}

9
filter: blur(0)为我做到了!
尼克

3
令人难以置信的O_o WTF与模糊?为什么默认打开它?
Yuriy Polezhayev

这也是我的解决方案。接受的答案可能适用于在转换属性中未使用其他“转换”功能的人,但不适用于我。
爱德华·科伊尔(Edward Coyle)

-webkit-前缀不应该出现吗?更多信息
Trevor Nestman

32

我推荐了一种实验性的新属性CSS,该CSS在最新的浏览器上进行了测试,效果很好:

image-rendering: optimizeSpeed;             /*                     */
image-rendering: -moz-crisp-edges;          /* Firefox             */
image-rendering: -o-crisp-edges;            /* Opera               */
image-rendering: -webkit-optimize-contrast; /* Chrome (and Safari) */
image-rendering: optimize-contrast;         /* CSS3 Proposed       */
-ms-interpolation-mode: nearest-neighbor;   /* IE8+                */

这样浏览器将知道渲染的算法


这修复了我模糊的旋转图像,而背面可见性,blur(0),translateZ对我不起作用。谢谢。
Louis Ameline 2015年

在某些用例中修复了图像,而在其他一些情况下则更糟:-)在任何情况下都很有趣!
西蒙·斯坦伯格2015年

深入研究:image-rendering: -webkit-optimize-contrast;解决了Chrome上的问题。但是,设置了渲染选项后,其他浏览器(例如Firefox)上的图像就会渲染得非常糟糕。因此,我仅使用WebKit指令,该指令也可在Blink引擎上使用。谢谢!
西蒙·斯坦伯格2015年

在某些情况下,它会导致图像明显锯齿。似乎在模糊结果与这个
令人叹为观止

4

刚刚发现了元素变形时变得模糊的另一个原因。transform: translate3d(-5.5px, -18px, 0);加载后,我一直在重新定位元素,但是该元素变得模糊了。

我尝试了上述所有建议,但结果却是由于我对转换值之一使用了十进制值。整数不会引起模糊,而且我离整数越远,模糊就越糟。

5.5px最模糊元素,5.1px最少。

只是以为我会在这里丢下它,以防它对任何人有帮助。


谢谢,这是我的问题-我使用的translateY(-50%)必须已经计算为小数像素值。
b4tch


2

扩展到两倍并降低到一半zoom对我有用。

transform: scale(2);
zoom: 0.5;

这似乎确实适用于Chrome浏览器中的图像。不幸的是,它也会修改您放置的所有html。
杰克·戴维森,

2

我已经尝试了大约10种可能的解决方案。混合它们,它们仍然不能正常工作。最后总是会有1px的抖动。

我通过减少过滤器的过渡时间来找到解决方案。

这不起作用:

.elem {
  filter: blur(0);
  transition: filter 1.2s ease;
}
.elem:hover {
  filter: blur(7px);
}

解:

.elem {
  filter: blur(0);
  transition: filter .7s ease;
}
.elem:hover {
  filter: blur(7px);
}

试试这个小提琴:

.blur {
  border: none;
  outline: none;
  width: 100px; height: 100px;
  background: #f0f;
  margin: 30px;
  -webkit-filter: blur(10px);
  transition: all .7s ease-out;
  /* transition: all .2s ease-out; */
}
.blur:hover {
  -webkit-filter: blur(0);
}

.blur2 {
  border: none;
  outline: none;
  width: 100px; height: 100px;
  background: tomato;
  margin: 30px;
  -webkit-filter: blur(10px);
  transition: all .2s ease-out;
}
.blur2:hover {
  -webkit-filter: blur(0);
}
<div class="blur"></div>

<div class="blur2"></div>

我希望这可以帮助别人。



1

对我来说,现在是2018年。解决我的问题(悬停在图像上的白色小闪烁线)唯一解决的问题是将其应用于我的链接元素,该链接元素包含具有 transform: scale(1.05)

a {
   -webkit-backface-visibility: hidden;
   backface-visibility: hidden;
   -webkit-transform: translateZ(0) scale(1.0, 1.0);
   transform: translateZ(0) scale(1.0, 1.0);
   -webkit-filter: blur(0);
   filter: blur(0);
}
a > .imageElement {
   transition: transform 3s ease-in-out;
}

是! 'blur(0)'在Chrome中为我修复了该问题。虽然使图像在调整大小时略微模糊,但不如跳转/调整大小那么明显
00-BBB

0
filter: blur(0)
transition: filter .3s ease-out
transition-timing-function: steps(3, end) // add this string with steps equal duration

设置过渡持续时间.3s等于过渡时间步长值对我有所帮助.3s


-7

刚遇到同样的问题。尝试设置position:相对于父元素,这对我有用。


5
你有这个工作的演示吗?我不知道这将如何帮助
Zach Saucier 2014年

2
如果可以的话,请编辑您的答案并解释所显示的代码的功能,以及该代码为何/如何回答问题,这确实可以提供帮助。单独的代码块通常不是有用的答案。
Lea Cohen 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.