CSS 过渡效果使图像模糊/移动图像1px,在 Chrome 中?

我有一些 CSS 悬停,一个 CSS 转换效果将移动一个 div。

正如您在示例中看到的那样,问题在于 translate转换产生了可怕的副作用,使得 div 中的图像向下/向右移动1px (可能还会略微调整大小?)所以它看起来不合适,不对焦。

这个小故障似乎在悬停效果应用的整个过程中都存在,从一个反复试验的过程来看,我可以放心地说,只有当平移转换移动 div 时才会出现(也应用了框阴影和不透明度,但是移除后对错误没有影响)。

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

178155 次浏览

2020年最新情况

  • 如果您有问题与模糊的图像,一定要检查从下面的答案,以及,特别是 image-rendering CSS 属性。
  • 对于最佳实践的可访问性和搜索引擎优化明智的您可以替换的背景图像与 <img>标签使用 合身的衣服 CSS 属性。

原始答案

在你的 CSS中试试这个:

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

这使得这个部门表现得“更加2D”。

  • 背面是作为默认绘制,以允许旋转翻转的东西 如果你只是顺时针向左、向右、向上、向下、比例或旋转(逆时针) ,就没有必要这样做。
  • 将 Z 轴平移为始终有一个零值。
  • Chrome 现在可以处理没有 -webkit-前缀的 backface-visibilitytransform。我目前还不知道这对其他浏览器的渲染有什么影响(FF,IE) ,所以要小心使用无前缀的版本。

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

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

或者

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

关于层创建条件的更多信息可以在这里阅读: Chrome 中的加速渲染


一种解释:

例子(悬浮绿色方块) :

当你在你的元素上使用任何过渡时,它会导致浏览器重新计算样式,然后重新布局你的内容,即使过渡属性是可视的(在我的例子中是不透明的) ,最后画一个元素:

screenshot

这里的问题是重新布局的内容,可以使“舞蹈”或“闪烁”的元素在页面上的效果,而过渡发生。 如果你打开设置,勾选“显示合成图层”复选框,然后对一个元素应用三维变换,你会看到它得到自己的橙色边框的图层。

screenshot

在元素得到自己的图层之后,浏览器只需要在过渡阶段合成图层,而不需要重新布局,甚至不需要绘制操作,所以问题必须得到解决:

screenshot

与嵌入的 youtube iframe 有同样的问题(翻译用于居中 iframe 元素)。以上所有的解决方案都不起作用,直到尝试了 重置 CSS 滤波器重置 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);
}

我推荐了一个实验性的新属性 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+                */

有了这个,浏览器就会知道渲染的算法

对我来说,使用 zoom将规模扩大到两倍并减少到一半是有效的。

transform: scale(2);
zoom: 0.5;

试试 filter: blur(0);

这招对我很管用

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

我尝试了以上所有的建议,但结果是由于我使用了一个十进制值的翻译值之一。整个数字不会造成侠影,我离整个数字越远侠影就变得越糟。

也就是说,5.5px模糊元素最多,5.1px模糊最少。

我只是想把这个扔在这里,以防对谁有帮助。

我利用过渡作弊问题,一步一步来,不是很顺利

transition-timing-function: steps(10, end);

它不是一种解决方案,它是一种欺骗,不能应用于任何地方。

我无法解释,但它对我很有用。没有其他答案可以帮助我(OSX,Chrome63,非视网膜显示)。

Https://jsfiddle.net/tuzae6a9/6/

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

通过设置转换持续时间 .3s的值等于转换计时步骤 .3s,我得到了帮助

我已经尝试了大约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>

我希望这能帮到别人。

对我来说,现在是2018年。唯一解决我的问题的方法是将这个方法应用到包含有 transform: scale(1.05)的图像元素的 link 元素上

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;
}

这些都不管用,对我管用的是缩小图像。

所以根据你想要的图像尺寸或者分辨率,你可以这样做:

.ok {
transform: perspective(100px) rotateY(0deg) scale(0.5);
transition: transform 1s;
object-fit:contain;
}
.ok:hover{
transform: perspective(100px) rotateY(-10deg) scale(0.5);
}


/* Demo Preview Stuff */
.bad {
max-width: 320px;
object-fit:contain;
transform: perspective(100px) rotateY(0deg);
transition: transform 1s;
}
.bad:hover{
transform: perspective(100px) rotateY(-10deg);
}


div {
text-align: center;
position: relative;
display: flex;
}
h3{
position: absolute;
bottom: 30px;
left: 0;
right: 0;
}
     

.b {
display: flex;
}
<center>
<h2>Hover on images</h2>
<div class="b">
<div>
<img class="ok" src='https://www.howtogeek.com/wp-content/uploads/2018/10/preview-11.png'>
<h3>Sharp</h3>
</div>


<div>
<img class="bad" src='https://www.howtogeek.com/wp-content/uploads/2018/10/preview-11.png'>
<h3>Blurry</h3>
</div>


</div>


</center>

图像应该缩小,确保你有一个大的图像分辨率

我有一个类似的问题与模糊的文本,但只有后续的 div 受到影响。由于某种原因,在我进行转换的那个 div 之后的下一个 div 是模糊的。

我尝试了这个帖子中推荐的所有方法,但都没有用。 对于我来说,重新排列我的碟片是可行的。我将模糊下面的 div 的 div 移到了父 div 的末尾。

如果有人知道为什么只是让我知道。

#before
<header class="container">
<div class="transformed div">
<span class="transform wrapper">
<span class="transformed"></span>
<span class="transformed"></span>
</span>
</div>
<div class="affected div">
</div>
</header>


#after
<header class="container">
<div class="affected div">
</div>
<div class="transformed div">
<span class="transform wrapper">
<span class="transformed"></span>
<span class="transformed"></span>
</span>
</div>


</header>

模糊只发生在我的 Chrome (Windows 和 Mac)动画’转换’在一个关键帧动画。对于我来说,webkit 优化对比度设置只起到了部分作用。为了得到最好的结果,我还必须为 scaleX 使用一个“神奇值”(比1稍大一点)。

下面是可行的代码:

img {
image-rendering: -webkit-optimize-contrast;
}


@keyframes scale-in-left {
0% {
transform: scaleX(0);
opacity: 0;
}
100% {
transform: scaleX(1.000001);
opacity: 1;
}
}

下面是无法正常工作的代码(在 Chrome 中导致图像模糊) :

@keyframes scale-in-left {
0% {
transform: scaleX(0);
opacity: 0;
}
100% {
transform: scaleX(1);
opacity: 1;
}
}

最后,“工作”代码消除了大部分的模糊,但不是全部。Safari 和 Firefox 在没有任何特殊设置的情况下更加清晰。

还要注意的是,只要调整浏览器窗口的大小,就可以清除不必要的模糊,这可能是导致 Chrome 无法执行最终渲染通行(?)的原因.