【问题标题】:CSS transition effect makes image blurry / moves image 1px, in Chrome?CSS过渡效果使图像模糊/将图像移动1px,在Chrome中?
【发布时间】:2013-03-06 00:51:28
【问题描述】:

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

问题是,正如您在示例中看到的那样,translate 转换具有可怕的副作用,即使 div 中的图像向下/向右移动 1px(并且可能会稍微调整大小?)所以它显得格格不入,失焦...

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

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

【问题讨论】:

  • 我在 OSX 上使用 Chrome 27,这很好。我相信当内容被放入图层时,它会在动画期间变成位图,并且在旧版本/旧显卡上这看起来不太好。尝试更新版本,看看是否已修复。
  • 在 Chrome 25 OS X 上一切正常。顺便说一句:我建议使用与 300KB 图像不同的背景渐变纹理方法!
  • 感谢@Paolo - 背景图片仅用于演示,不是实际网站上使用的图片!
  • 当动画由 GPU 处理时出现问题,看起来位图四舍五入有点偏离。在 Canary 中复现,但如果你关闭 GPU 加速,它就可以正常工作
  • 你可以每帧都试试这个解决方案...stackoverflow.com/a/42256897/1834212

标签: css image hover positioning translate-animation


【解决方案1】:

2020 年更新

  • 如果您遇到图像模糊问题,请务必检查下面的答案,尤其是 image-rendering CSS 属性。
  • 为了获得最佳实践可访问性和 SEO,您可以使用 object-fit CSS 属性将背景图片替换为 <img> 标记。

原答案

在你的 CSS 中试试这个:

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

这样做的目的是让分区表现得“更加二维”。

  • 默认绘制背面以允许使用旋转翻转物体 等等。如果您只是顺时针向左、向右、向上、向下、缩放或旋转(逆时针),则无需这样做。
  • 平移 Z 轴始终为零值。
  • Chrome 现在可以处理 backface-visibilitytransform 而没有 -webkit- 前缀。我目前不知道这会如何影响其他浏览器的渲染(FF、IE),所以请谨慎使用不带前缀的版本。

【讨论】:

  • 可能没有解释什么,但它解释得足以为我解决这个问题。
  • @Class Stacker - 要解释什么?您只需将代码复制粘贴到有问题的元素。顺便说一句,这很好用!
  • 我建议这个解决方案stackoverflow.com/a/42256897/1834212我发布链接以避免重复
  • 有人可以确认这是否仍然有效,因为每当我添加 `-webkit-backface-visibility` 和 -webkit-transform 时,我都看不到变化,当我打开 chromes 开发者控制台时。我看到这 2 个 css 属性被划过,好像它们被覆盖了,但它们不是(空的 css 和 html)。就好像 chrome 不再接受它们一样。
  • @KevinM 尝试不带 -webkit- 前缀,这些现在是标准 CSS。
【解决方案2】:

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

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

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

有关图层创建标准的更多信息,您可以在此处阅读:Accelerated Rendering in Chrome


解释:

示例(悬停绿色框):

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

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

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

【讨论】:

  • 好东西!明白了你的答案有多详细的原因!您使用哪个软件进行屏幕捕获/箭头?
  • 看队友!!在那里为我省去了很多麻烦。
  • 这对我有用。起初我在动画的父对象上使用 translateZ,但其中的背景图像精灵仍然模糊。我正在使用 Velocity.js 在其中扩展另一个容器并应用类似translateZ: 0.000001(一些无穷小#)的东西,瞧!再次清晰的背景图像!
  • 谢谢伙计。这对我的问题有效。顺便说一句,我的问题是我有一个旋转 90 度的元素,并且使用不透明度进行淡入过渡。触发过渡时,元素的内容从左侧移动 1px。
【解决方案3】:

嵌入 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);
}

【讨论】:

  • filter: blur(0) 为我做了!
  • 令人难以置信的 O_o WTF 与模糊?为什么默认开启?
  • 这也是我的解决方案。接受的答案可能适用于未在其转换属性中使用其他“翻译”功能的人,但它不适用于我。
  • 不应该是-webkit-前缀吗? More Info
【解决方案4】:

我推荐了一个我在最新浏览器上测试过的实验性新属性 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 对我不起作用。谢谢。
  • 在某些用例中修复了图像,在另一些用例中变得更糟:-)无论如何都很有趣!
  • 深入挖掘:image-rendering: -webkit-optimize-contrast; 解决了 Chrome 上的问题。但是,其他浏览器上的图像,例如Firefox,使用渲染选项集渲染得非常非常糟糕。因此,我只使用 WebKit 指令,它也适用于 Blink 引擎。谢谢!
  • 在某些情况下,它会导致图像明显参差不齐。在模糊的结果和这个结果之间似乎找不到一个最佳点~叹气~
  • 不再是optimizeSpeed,而是pixalated -> 见mozilla website
【解决方案5】:

使用zoom 将规模扩大一倍并减少一半对我有用。

transform: scale(2);
zoom: 0.5;

【讨论】:

  • 这似乎在 chrome 中适用于图像。不幸的是,它也会修改您放置的任何 html。
【解决方案6】:

试试filter: blur(0);

它对我有用

【讨论】:

  • 对我也有用,Chrome 63、64 和 Vivaldi 1.13
【解决方案7】:

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

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

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

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

【讨论】:

  • 谢谢,这就是我的问题——我使用的是 translateY(-50%),它一定是在计算十进制像素值。
【解决方案8】:

我用分步过渡作弊的问题,不顺利

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

不是解决,是作弊,不能到处套用。

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

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

【讨论】:

  • 你的小提琴像帕金森一样颤抖,但在我的情况下有效。
【解决方案9】:
filter: blur(0)
transition: filter .3s ease-out
transition-timing-function: steps(3, end) // add this string with steps equal duration

设置转换持续时间的值 .3s 等于转换时间步长 .3s 对我有帮助

【讨论】:

    【解决方案10】:

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

    我希望这对某人有所帮助。

    【讨论】:

      【解决方案11】:

      对我来说,现在是 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 中为我修复了它。虽然在调整大小时使图像非常模糊,但比跳转/调整大小不那么明显
      【解决方案12】:

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

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

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

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

      【讨论】:

        【解决方案13】:

        我遇到了类似的模糊文本问题,但只有后面的 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>
        

        【讨论】:

          【解决方案14】:

          在关键帧动画中为“变换”设置动画时,仅在 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 无法执行最终渲染过程 (?)。

          【讨论】:

            猜你喜欢
            • 2018-09-26
            • 2014-03-18
            • 2012-03-05
            • 1970-01-01
            • 1970-01-01
            • 2012-11-20
            • 1970-01-01
            • 2015-07-16
            • 2021-05-14
            相关资源
            最近更新 更多