Ефект переходу CSS робить зображення розмитим / переміщує зображення на 1px в Chrome?


150

У мене є CSS, що після наведення ефекту переходу CSS буде переміщено діл.

Проблема, як ви бачите в прикладі, полягає в тому, що translateперехід має жахливий побічний ефект - змусити зображення в діві рухатись на 1px вниз / вправо (і, можливо, змінювати розмір коли-небудь так трохи?), Щоб воно з'явилося поза місцем і поза увагою ...

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

Здається, проблема виникає лише тоді, коли на сторінці є смуги прокрутки. Отже, приклад із лише одним екземпляром 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".

  • Backface малюється за замовчуванням, щоб дозволити гортати речі з обертанням тощо. У цьому немає необхідності, якщо ви рухаєтеся лише вліво, вправо, вгору, вниз, масштабуйте або обертаєте (проти -) за годинниковою стрілкою.
  • Перекладіть вісь Z так, щоб вона завжди мала нульове значення.
  • Зараз Chrome обробляє backface-visibilityта transformбез -webkit-префікса. На даний момент я не знаю, як це впливає на рендеринг інших браузерів (FF, IE), тому використовуйте нефіксовані версії з обережністю.

27
Можливо, нічого б не пояснили, але це досить пояснило, щоб виправити цю проблему для мене.
McNab

@Class Stacker - що пояснити? Ви просто скопіюйте вставити код на свій проблемний елемент. До речі, це працює дуже приємно!
easwee

1
Я пропоную це рішення stackoverflow.com/a/42256897/1834212 я розміщую посилання, щоб уникнути дублювання
Мігель

1
Чи можу хтось підтвердити, чи все-таки це працює, тому що коли я додаю ` -webkit-transform-webkit-backface-vidibility`, і я не можу реально побачити зміни, і коли я відкриваю консоль розробника Chrome. Я бачу, що ці 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


Пояснення:

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

Коли ви використовуєте будь-який перехід на своєму елементі, це змушує браузер перерахувати стилі, а потім переплануйте вміст, навіть якщо властивість переходу є візуальною (у моїх прикладах це непрозорість) і остаточно намалюйте елемент:

скріншот

Проблема тут полягає в переплануванні вмісту, який може зробити ефект "танцюючих" або "блимаючих" елементів на сторінці під час переходу. Якщо ви перейдете до налаштувань, поставте прапорець "Показати складені шари", а потім застосуйте 3d перетворення до елемента, ви побачите, що він отримує свій власний шар, який окреслений помаранчевою рамкою.

скріншот

Після того, як елемент отримує власний шар, браузер просто повинен складати шари на переході без перестановки або навіть операцій з фарбуванням, тому проблему потрібно вирішити:

скріншот


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

Пляма на товари !! Там врятували мені багато клопоту.

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

Дякую, друже. Це спрацювало над моєю проблемою. до речі, моя проблема полягає в тому, що у мене є елемент, який обертається на 90 градусів і має перехід із затуханням, використовуючи непрозорість. при запуску переходу вміст елемента рухається 1px зліва.
Ллойд Аарон

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
Неймовірно O_o WTF з розмиттям? Чому він увімкнено за замовчуванням?
Юрій Поляжаєв

Це було рішення і для мене. Прийнята відповідь могла працювати для людей, які не використовують інші функції «перекладу» у своїх властивостях перетворення, але це не працювало для мене.
Едвард Койл-молодший

Чи не повинен -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, дисплей, що не стосується сітківки).

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


У вашій скрипці тремтить, як у Паркінсона, але в моєму випадку спрацювало.
Tárcio Zemel

2

Масштабування вдвічі і зведення до половини, zoomпрацюючи для мене.

transform: scale(2);
zoom: 0.5;

це, здається, працює в хромі для зображень. на жаль, він також змінює будь-який 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

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

Це працювало для мене


Для мене також працювали Chrome 63, 64 та Vivaldi 1.13
GTCrais

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
У вас демонстрація цього робочого? Я не маю уявлення, як це допомогло б
Зак Сосьє

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