CSS-эффект перехода делает изображение размытым / перемещает изображение на 1 пиксель в Chrome?

У меня есть CSS, при наведении которого эффект перехода CSS перемещает div.

Проблема, как вы можете видеть в примере, заключается в том, что переход translate имеет ужасный побочный эффект: изображение в div перемещается на 1 пиксель вниз / вправо (и, возможно, немного изменяет размер?), Так что оно кажется неуместным. и не в фокусе ...

Кажется, что сбой применяется все время, пока применяется эффект наведения, и из процесса проб и ошибок я могу с уверенностью сказать, что кажется, что он возникает только тогда, когда переход перевода перемещает div (тень и непрозрачность блока также применяются, но не имеют никакого значения для ошибка при удалении).

Проблема возникает только тогда, когда на странице есть полосы прокрутки. Таким образом, пример с одним экземпляром div хорош, но когда добавляются еще одни идентичные div, и поэтому для страницы требуется полоса прокрутки, проблема снова возникает ...


person Lewis    schedule 17.03.2013    source источник
comment
Я использую Chrome 27 на OS X, и все в порядке. Я считаю, что когда контент помещается в слой, он превращается в растровое изображение во время анимации, и что на более старых версиях / старых видеокартах это выглядит не очень хорошо. Попробуйте более новую версию и посмотрите, исправлена ​​ли она.   -  person Rich Bradshaw    schedule 17.03.2013
comment
В Chrome 25 OS X все нормально. Кстати: я бы предложил другой подход для текстуры градиента фона, чем изображение размером 300 КБ!   -  person Paolo    schedule 17.03.2013
comment
И спасибо @Paolo - фоновое изображение предназначалось только для демонстрации, а не на реальном сайте!   -  person Lewis    schedule 17.03.2013
comment
Проблема возникает, когда анимация обрабатывается графическим процессором, похоже, что округление растровых изображений немного неверно. Воспроизводится на Canary, но работает нормально, если вы отключите ускорение графического процессора.   -  person vals    schedule 18.03.2013
comment
Вы можете пробовать это решение в каждом кадре ... stackoverflow.com/a/42256897/1834212   -  person Miguel    schedule 15.02.2017
comment
Я обнаружил, что эта проблема возникает только в том случае, если в браузере есть масштабирование. вы можете сбросить с помощью CTR + 0 / CMD + 0   -  person Nathan Redblur    schedule 08.02.2018
comment
Если ваша проблема - translateX/translateY центрирование и вы знаете размеры элемента, вы всегда можете вернуться к классическому отрицательному полю, равному половине размера центрированного элемента. и если ваш элемент имеет размер 1px, просто не переводите, это не имеет смысла, если вы уже на 50% увеличили размер 1px :).   -  person jave.web    schedule 15.02.2020


Ответы (13)


Обновление 2020

  • Если у вас есть проблемы с размытыми изображениями, обязательно проверьте ответы снизу, особенно свойство image-rendering CSS.
  • Для лучшей доступности и с точки зрения SEO вы можете заменить фоновое изображение тегом <img>, используя объектно-подходящего свойства CSS.

Оригинальный ответ

Попробуйте это в своем CSS:

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

Это заставляет разделение вести себя более 2D.

  • Задняя сторона рисуется по умолчанию, чтобы можно было переворачивать объекты с помощью поворота и т. Д. В этом нет необходимости, если вы двигаетесь только влево, вправо, вверх, вниз, масштабируете или вращаете (против) по часовой стрелке.
  • Переведите ось Z, чтобы всегда иметь нулевое значение.
  • Chrome теперь обрабатывает backface-visibility и transform без префикса -webkit-. В настоящее время я не знаю, как это влияет на рендеринг в других браузерах (FF, IE), поэтому используйте версии без префиксов с осторожностью.
person sampoh    schedule 18.03.2013
comment
Возможно, ничего не объяснил, но объяснил достаточно, чтобы решить эту проблему для меня. - person McNab; 29.03.2013
comment
@Class Stacker - что объяснять? Вы просто копируете и вставляете код в проблемный элемент. Кстати, это работает очень хорошо! - person easwee; 02.07.2013
comment
Сработало для меня как шарм, даже в Firefox: O - person Ms01; 29.10.2013
comment
Я могу согласиться с тем, что это исправляет ряд проблем с рендерингом даже в Firefox (без префикса, конечно) ... спасибо rampapapa. - person mkoistinen; 12.01.2014
comment
Иногда проблемы вызваны шириной поплавка, например 300,12 пикселей. - person Rantiev; 03.05.2014
comment
@Rantiev, можете ли вы изменить эту скрипку, чтобы можно было воспроизвести проблему? Какую версию Chrome вы используете? jsfiddle.net/tf3xa/1 - person sampoh; 04.05.2014
comment
@sampoh Привет, Вы работаете в команде Chrome? Недавно я обнаружил, что последние версии Chrome содержат меньше ошибок, связанных с шириной поплавка и т. Д., Но они присутствуют. Я не могу найти пример сейчас, но предоставлю ссылку, если я столкнусь с такой проблемой. - person Rantiev; 05.05.2014
comment
@Rantiev, нет, но я польщен: P Просто пытаюсь найти лучшее решение проблемы. - person sampoh; 06.05.2014
comment
@ user1672694 ты прав. Chrome выполняет рендеринг и фильтрацию изображений. Вот скрипка, которая показывает немного резче левую сторону кота через некоторое время, когда анимация остановилась. Иногда вы также замечаете небольшой сдвиг в изображении. - person sampoh; 05.05.2015
comment
Вы также можете попробовать SVG. Вот пример codepen.io/Izaias/pen/WvWxxv - person Izaias; 12.08.2015
comment
Не работает с «transform: translateY (-50%) translateZ (0)» и «transform: translate3d (0, -50%, 0)». Почему? - person Fred K; 28.03.2016
comment
@FredK, у вас может быть только одно свойство преобразования, верно? Кажется, это работает на моих тестах скрипки. .my-cat { -webkit-backface-visibility: hidden; transform: translateZ(0) translateY(-50%) scale(1, 1); } .my-cat:hover { transform: translateZ(0) translateY(-50%) scale(1.3, 1.3); } - person sampoh; 30.03.2016
comment
Это сработало для меня, но я использовал только часть обратной видимости. TranslateZ скинул мое позиционирование. Спасибо! - person chris; 09.04.2016
comment
это отлично работает, но делает другие элементы, такие как абзацы, размытыми. есть идеи, как это исправить? - person doubleOrt; 03.09.2016
comment
@Double, как упоминал Рантьев, это размытие вызывают субпиксели. И я считаю, что именно по этой причине происходит сдвиг пикселей. Теперь вы можете попробовать анимацию с font-size, она выглядит неплохо, но с ней довольно сложно справиться. - person sampoh; 03.09.2016
comment
@Rantiev анимация размера шрифта, как что? есть ссылки по теме? - person doubleOrt; 03.09.2016
comment
Этот ответ также должен включать версии свойств, отличных от -webkit-. Chrome отключает свойства здесь и игнорирует их как недопустимые. Теперь он будет принимать только варианты, не относящиеся к webkit. - person Routhinator; 15.12.2016
comment
@Routhinator Я был бы счастлив, но ... есть вероятность, что это заставит другие браузеры вести себя странно, верно? У меня нет времени проверять это сейчас, но если кто-то может это проверить, просто пингуйте меня, и я также отредактирую определения с префиксом сторонних производителей. - person sampoh; 09.01.2017
comment
Я предлагаю это решение stackoverflow.com/a/42256897/1834212, размещая ссылку, чтобы избежать дублирования - person Miguel; 15.02.2017
comment
Может ли кто-нибудь подтвердить, что это все еще работает, потому что всякий раз, когда я добавляю `-webkit-backface-visibility` и -webkit-transform, я действительно не вижу изменений, и когда я открываю консоль разработчика хромов. Я вижу, что эти 2 свойства css обведены, как будто они перезаписаны, но это не так (пустые css и html). Как будто хром их больше не принимает. - person Kevin M; 16.03.2017
comment
@KevinM попробуйте без префиксов -webkit-, теперь это стандартный CSS. - person sampoh; 30.03.2017
comment
Это не решает проблему. Это фактически делает весь контент более размытым, чем раньше ... - person Federico Schiocchet; 24.09.2019
comment
Не используйте translateZ(0), если в этом нет необходимости. Он разрушает модель иерархии DOM и изолирует всех дочерних элементов от родителя. - person Roman Belov; 14.02.2020

Вам нужно применить к элементу трехмерное преобразование, чтобы он получил свой собственный составной слой. Например:

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

or

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

Подробнее о критериях создания слоев вы можете прочитать прямо здесь: Ускоренный рендеринг в Chrome


Объяснение:

Примеры (наведите курсор на зеленый прямоугольник):

Когда вы используете какой-либо переход в своем элементе, это заставляет браузер пересчитывать стили, а затем перестраивать ваш контент, даже если свойство перехода является визуальным (в моих примерах это непрозрачность) и, наконец, раскрашивать элемент:

скриншот

Проблема здесь в изменении макета содержимого, которое может создавать эффект «танцующих» или «мигающих» элементов на странице во время перехода. Если вы перейдете в настройки, установите флажок «Показать составные слои», а затем примените трехмерное преобразование к элементу, вы увидите, что он получает свой собственный слой, обведенный оранжевой рамкой.

скриншот

После того, как элемент получает свой собственный слой, браузеру просто нужно составить слои при переходе без повторного макета или даже операций рисования, поэтому проблема должна быть решена:

скриншот

person sol0mka    schedule 06.10.2013
comment
хорошая штука! понял, насколько подробным был ваш ответ! какое программное обеспечение вы используете для захвата экрана / перемещения курсора? - person kroe; 03.12.2013
comment
Пятно на мате !! Это избавило меня от лишних хлопот. - person ; 10.03.2014
comment
Это помогло мне. Сначала я использовал translateZ для родительского элемента, который я анимировал, но спрайты фонового изображения внутри все еще были размытыми. Я использую Velocity.js для масштабирования еще одного контейнера внутри него и применяю что-то вроде translateZ: 0.000001 (какой-то бесконечно малый #) и вуаля! И снова четкие фоновые изображения! - person notacouch; 06.11.2015
comment
Спасибо друг. Это сработало с моей проблемой. кстати, моя проблема в том, что у меня есть элемент, который повернут на 90 градусов и имеет плавный переход с использованием непрозрачности. при запуске перехода содержимое элемента перемещается на 1 пиксель слева. - person Lloyd aaron; 12.09.2016

Была та же проблема со встроенным iframe youtube (для центрирования элемента 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);
}
person xb1itz    schedule 17.02.2015
comment
filter: blur(0) сделал это за меня! - person Nick; 08.09.2015
comment
Невероятно О_о Чёрт с размытием? Почему он включен по умолчанию? - person Yuriy Polezhayev; 29.01.2016
comment
Это было решением и для меня. Принятый ответ может сработать для людей, которые не используют другие функции перевода в своих свойствах преобразования, но у меня это не сработало. - person Edward Coyle Jr.; 18.02.2016
comment
Разве префикс -webkit- не должен стоять раньше? Дополнительная информация - person Trevor Nestman; 12.01.2017

Я порекомендовал экспериментальный новый атрибут 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+                */

Благодаря этому браузер узнает алгоритм рендеринга.

person Felipez    schedule 05.03.2015
comment
Это исправило мои размытые повернутые изображения, в то время как backface-visibility, blur (0), translateZ у меня не работали. Спасибо. - person Louis Ameline; 11.09.2015
comment
Исправлены изображения в некоторых случаях использования, в некоторых случаях стало ужасно хуже :-) В любом случае интересно! - person Simon Steinberger; 03.11.2015
comment
Копаем глубже: image-rendering: -webkit-optimize-contrast; решает проблему в Chrome. Однако изображения в других браузерах, например Firefox, с установленной опцией рендеринга, рендерится намного, намного хуже. Поэтому я использую только директиву WebKit, которая также работает на движке Blink. Спасибо! - person Simon Steinberger; 03.11.2015
comment
В некоторых случаях это приводит к тому, что изображения становятся заметно неровными. Кажется, не могу найти золотую середину между более размытым результатом и этим ~ вздох ~ - person bigp; 09.01.2016
comment
Это больше не optimizeSpeed, а pixalated - ›см. На веб-сайте mozilla - person Raphaël Balet; 09.02.2021

Только что нашел еще одну причину, по которой элемент становится размытым при преобразовании. Я использовал transform: translate3d(-5.5px, -18px, 0); для изменения положения элемента после его загрузки, однако этот элемент стал размытым.

Я попробовал все приведенные выше предложения, но оказалось, что это произошло из-за того, что я использовал десятичное значение для одного из значений перевода. Целые числа не вызывают размытия, и чем дальше я отходил от целого числа, тем хуже становилось размытие.

т.е. 5.5px размывает элемент больше всего, 5.1px меньше всего.

Просто подумал, что брошу это сюда, если это кому-нибудь поможет.

person ashrobbins    schedule 14.12.2017
comment
Спасибо, это была проблема в моем случае - я использовал translateY (-50%), который, должно быть, оценивал значение десятичного пикселя. - person b4tch; 14.02.2018

Обдумал задачу, используя переход по шагам, а не плавно

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

Это не решение, это обман, и его нельзя применять везде.

Я не могу это объяснить, но у меня это работает. Ни один из других ответов мне не помогает (OSX, Chrome 63, дисплей без Retina).

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

person Evgeny Gendel    schedule 12.01.2018
comment
В твоей скрипке трясется как у Паркинсона, но в моем случае сработало. - person Tárcio Zemel; 03.02.2018

У меня сработало увеличение вдвое и уменьшение до половины с помощью zoom.

transform: scale(2);
zoom: 0.5;
person Kushagra Gour    schedule 11.05.2016
comment
похоже, это работает в хроме для изображений. к сожалению, он также изменяет любой HTML-код, который вы его размещаете. - person Jack Davidson; 02.05.2019

Попробуйте filter: blur(0);

Это сработало для меня

person Fred K    schedule 05.06.2017
comment
У меня тоже работал, Chrome 63, 64 и Vivaldi 1.13 - person GTCrais; 27.01.2018

Я пробовал около 10 возможных решений. Их перепутали, и они все равно не работали правильно. В конце всегда было встряхивание на 1 пиксель.

Я нахожу решение, уменьшая время перехода на фильтр.

Это не сработало:

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

Я надеюсь, что это помогает кому-то.

person Adam Orlov    schedule 21.03.2018

Для меня сейчас в 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;
}
person mateostabio    schedule 29.04.2018
comment
Да! Размытие (0) исправляет это в Chrome. Делает изображение очень слегка размытым при изменении размера, но менее заметно, чем при переходе / изменении размера. - person 00-BBB; 16.05.2019

Ничего из этого не сработало, у меня сработало уменьшение изображения.

Итак, в зависимости от того, какого размера вы хотите изображение или какого разрешения ваше изображение, вы можете сделать что-то вроде этого:

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

Изображение должно быть уменьшено, убедитесь, что у вас большое разрешение изображения.

person True Kapo    schedule 15.01.2021

У меня была аналогичная проблема с размытым текстом, но затронула только следующий 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>
person Johannes Ludloff    schedule 29.01.2021

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

Мне помогла установка значения продолжительности перехода .3s равными шагам времени перехода .3s

person j-tap    schedule 01.03.2018