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


150

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

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

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

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


1
Я на Chrome 27 на OSX, и это нормально. Я считаю, что когда контент помещается в слой, он превращается в растровое изображение во время анимации, и что на старых версиях / старых видеокартах это выглядит не очень хорошо. Попробуйте более новую версию и посмотрите, исправлена ​​ли она.
Рич Брэдшоу

Все хорошо на Chrome 25 OS X. Кстати: я бы предложил другой подход для фоновой текстуры градиента, чем изображение размером 300 КБ!
Паоло

И спасибо @Paolo - фоновое изображение было только для демонстрации, это не изображение, используемое на реальном сайте!
Льюис

2
Проблема возникает, когда анимация обрабатывается графическим процессором, похоже, что округления растровых изображений немного отключены. Воспроизводится на Canary, но работает нормально, если отключить ускорение GPU
vals

Вы можете попробовать это решение каждый кадр ... stackoverflow.com/a/42256897/1834212
Мигель

Ответы:


247

Обновление 2020

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

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

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

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

То, что это делает, заставляет подразделение вести себя «более 2D».

  • Задняя поверхность рисуется по умолчанию, чтобы можно было переворачивать объекты с помощью rotate и тому подобное. В этом нет необходимости, если вы двигаетесь влево, вправо, вверх, вниз, масштабируете или поворачиваете (против) по часовой стрелке.
  • Переведите ось Z, чтобы всегда иметь нулевое значение.
  • Хром теперь обрабатывает backface-visibilityи transformбез -webkit-префикса. В настоящее время я не знаю, как это влияет на рендеринг других браузеров (FF, IE), поэтому используйте версии без префиксов с осторожностью.

27
Возможно, ничего не объяснил, но объяснил достаточно, чтобы решить эту проблему для меня.
McNab

@ Class Stacker - что объяснить? Вы просто копируете и вставляете код в проблемный элемент. Кстати, это работает очень хорошо!
easwee

1
я предлагаю это решение stackoverflow.com/a/42256897/1834212 я
Мигель

1
Может ли кто-нибудь подтвердить, что это все еще работает, потому что всякий раз, когда я добавляю `-webkit-backface-visibility` и -webkit-transform, я не вижу изменений, и когда открываю консоль разработчика chromes. Я вижу, что эти 2 свойства CSS обведены, как будто они перезаписаны, но это не так (пустые CSS и HTML). Как будто хром больше не принимает их.
Кевин М

1
@KevinM попробуйте без префиксов -webkit-, теперь это стандартный CSS.
Сампо

91

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

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

или

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

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


Объяснение:

Примеры (наведите зеленую рамку):

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

Скриншот

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

Скриншот

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

Скриншот


хорошие вещи! получил точную причину того, насколько подробным был ваш ответ! какое программное обеспечение вы используете для захвата экрана / стрелки?
Кро

Пятно на мате !! Спасло меня много хлопот там.

Это помогло мне. Сначала я использовал translateZ на родительском объекте, который я анимировал, но спрайты фонового изображения все еще были размыты. Я использую Velocity.js для масштабирования еще одного контейнера внутри него и применил что-то вроде translateZ: 0.000001(некоторые бесконечно малые #) и вуаля! Резкие фоновые изображения еще раз!
notacouch

Спасибо друг. Это сработало на моей проблеме. Кстати, моя проблема в том, что у меня есть элемент, который вращается на 90 градусов и имеет постепенный переход с использованием прозрачности. при запуске перехода содержимое элемента перемещается на 1 пиксель слева.
Ллойд Аарон

42

Была такая же проблема с встраиваемым 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);
}

9
filter: blur(0)сделал это для меня!
Ник

3
Невероятный О_о WTF с размытостью? Почему он включен по умолчанию?
Юрий Полежаев

Это было решением для меня тоже. Принятый ответ может сработать для людей, которые не используют другие функции "translate" в своих свойствах преобразования, но это не сработало для меня.
Эдвард Койл младший

Разве -webkit-префикс не должен стоять раньше? Дополнительная информация
Тревор Нестман

32

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

При этом браузер узнает алгоритм рендеринга


Это исправило мои размытые повернутые изображения, в то время как обратная видимость, размытие (0), translateZ не работали для меня. Спасибо.
Луи Амелин

Исправлены изображения в некоторых случаях, из-за чего было ужасно хуже в других :-) Интересно в любом случае!
Саймон Стейнбергер,

Копаем глубже: image-rendering: -webkit-optimize-contrast;решает проблему с Chrome. Тем не менее, изображения в других браузерах, например Firefox, отображаются гораздо хуже, с установленным параметром рендеринга. Поэтому я использую только директиву WebKit, которая также работает на движке Blink. Спасибо!
Саймон Стейнбергер,

В некоторых случаях это приводит к тому, что изображения становятся заметно неровными. Кажется, я не могу найти точку между результатом размытия и этим ~ вздох ~
bigp

4

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

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

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

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


Спасибо, это была проблема в моем случае - я использовал translateY (-50%), который должен был вычисляться до десятичного значения в пикселях.
b4tch

3

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

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

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

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

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


У тебя скрипит дрожь как у Паркинсона, но в моем случае сработало.
Тарсио Земель

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

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


5
У вас есть демо этой работы? Я понятия не имею, как это могло бы помочь
Зак Saucier

2
Если бы вы могли отредактировать свой ответ и объяснить, что делает код, который вы показываете, и почему / как этот код отвечает на вопрос, это действительно может помочь. Блоки кода сами по себе обычно не являются полезными ответами.
Леа Коэн
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.