166

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

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

故障似乎在应用悬停效果的整个过程中都存在,并且从反复试验的过程中,我可以肯定地说似乎只在平移转换移动 div 时发生(也应用了框阴影和不透明度,但对删除时的错误)。

该问题似乎仅在页面具有滚动条时发生。因此,只有一个 div 实例的示例很好,但是一旦添加了更多相同的 div 并且页面因此需要滚动条,问题再次出现......

4

14 回答 14

273

2020 年更新


原始答案

在你的CSS中试试这个:

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

这样做的目的是使该部门表现得“更加二维”。

  • 背面是默认绘制的,以允许使用旋转等翻转事物。如果您只向左、向右、向上、向下、缩放或旋转(逆时针)顺时针,则没有必要这样做。
  • 平移 Z 轴以始终具有零值。
  • Chrome 现在可以处理backface-visibility并且transform没有-webkit-前缀。我目前不知道这会如何影响其他浏览器的渲染(FF、IE),所以请谨慎使用不带前缀的版本。
于 2013-03-18T08:22:55.877 回答
99

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

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

或者

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

有关图层创建标准的更多信息,您可以在此处阅读:Chrome 中的加速渲染


一个解释:

示例(悬停绿色框):

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

截屏

这里的问题是内容的重新布局,可以在转换发生时在页面上产生“跳舞”或“闪烁”元素的效果。如果您将进入设置,选中“显示复合图层”复选框,然后将 3d 变换应用于元素,您将看到它拥有自己的图层,该图层带有橙色边框。

截屏

元素获得自己的图层后,浏览器只需在过渡时合成图层,无需重新布局甚至绘制操作,因此必须解决问题:

截屏

于 2013-10-06T17:52:55.613 回答
47

嵌入的 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);
}
于 2015-02-17T15:48:42.000 回答
35

我推荐了一个我在最新浏览器上测试过的实验性新属性 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+                */

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

于 2015-03-05T16:13:41.447 回答
6

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

我尝试了上面的所有建议,但事实证明这是由于我对其中一个翻译值使用了十进制值。整数不会导致模糊,我离整数越远,模糊就越严重。

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

只是想我会把这个扔在这里,以防它对任何人有帮助。

于 2017-12-14T10:11:57.613 回答
3

我使用逐步过渡欺骗了问题,不顺利

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

这不是解决,而是作弊,不能到处应用。

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

https://jsfiddle.net/tuzae6a9/6/

于 2018-01-12T19:15:14.023 回答
2

对我来说,现在是 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;
}
于 2018-04-29T02:12:54.580 回答
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>

我希望这可以帮助别人。

于 2018-03-21T11:51:26.913 回答
2

缩放到两倍并降低到一半zoom对我有用。

transform: scale(2);
zoom: 0.5;
于 2016-05-11T10:42:33.627 回答
2

尝试filter: blur(0);

它对我有用

于 2017-06-05T14:15:40.543 回答
1

这些都不起作用,对我有用的是缩小图像。

因此,根据您想要图像的大小或图像的分辨率,您可以执行以下操作:

.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>

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

于 2021-01-15T20:43:11.300 回答
1

我对模糊文本也有类似的问题,但只有后面的 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>
于 2021-01-29T23:36:06.123 回答
0
filter: blur(0)
transition: filter .3s ease-out
transition-timing-function: steps(3, end) // add this string with steps equal duration

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

于 2018-03-01T09:13:40.223 回答
0

在关键帧动画中为“转换”设置动画时,仅在 Chrome(Windows 和 Mac)中发生模糊。对我来说,-webkit-optimize-contrast 设置只是部分帮助。为了获得最佳效果,我还必须对 scaleX 使用“魔术值”(略大于 1 而不是 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 无法执行最终渲染过程 (?)。

于 2021-10-22T00:10:23.923 回答