El efecto de transición CSS hace que la imagen sea borrosa / mueve la imagen 1px, en Chrome?

150

Tengo algo de CSS que al pasar el mouse, un efecto de transición de CSS moverá un div.

El problema, como puede ver en el ejemplo, es que la translatetransición tiene el horrible efecto secundario de hacer que la imagen en el div se mueva 1px hacia abajo / derecha (¿y posiblemente cambiar el tamaño muy ligeramente?) Para que parezca fuera de lugar y fuera de foco...

La falla parece aplicarse todo el tiempo que se aplica el efecto de desplazamiento, y a partir de un proceso de prueba y error, puedo decir con seguridad que solo parece ocurrir cuando la transición de traslación mueve el div (la sombra y la opacidad de la caja también se aplican pero no hacen ninguna diferencia para El error cuando se elimina).

El problema solo parece suceder cuando la página tiene barras de desplazamiento. Entonces, el ejemplo con solo una instancia del div está bien, pero una vez que se agregan divs idénticos y la página requiere una barra de desplazamiento, el problema vuelve a ocurrir ...

Luis
fuente
1
Estoy en Chrome 27 en OSX, y está bien. Creo que cuando el contenido se pone en una capa, se convierte en un mapa de bits durante la animación, y que en versiones anteriores / tarjetas gráficas anteriores esto no se ve muy bien. Pruebe una versión más nueva y vea si está arreglada.
Rich Bradshaw
Todo bien en Chrome 25 OS X. BTW: ¡Sugeriría un enfoque diferente para la textura de gradiente de fondo que una imagen de 300 KB!
Paolo
Y gracias @Paolo: la imagen de fondo fue solo para la demostración, ¡no es la imagen en uso en el sitio real!
Lewis
2
El problema surge cuando la animación es manejada por la GPU, parece que los redondeos de mapa de bits están un poco apagados. Se reproduce en Canarias, pero funciona bien si desactiva la aceleración de la GPU
vals
Puede probar esta solución cada fotograma ... stackoverflow.com/a/42256897/1834212
Miguel

Respuestas:

247

Actualización 2020

  • Si tiene problemas con las imágenes borrosas, asegúrese de verificar las respuestas a continuación también, especialmente la image-renderingpropiedad CSS.
  • Para una mejor práctica de accesibilidad y SEO, puede reemplazar la imagen de fondo con una <img>etiqueta usando la propiedad CSS de ajuste de objeto .

Respuesta original

Prueba esto en tu CSS :

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

Lo que esto hace es que la división se comporte "más 2D".

  • La cara posterior se dibuja por defecto para permitir voltear cosas con rotar y tal. No hay necesidad de eso si solo se mueve hacia la izquierda, derecha, arriba, abajo, escala o gira (en sentido antihorario).
  • Traslade el eje Z para que siempre tenga un valor cero.
  • Chrome ahora maneja backface-visibilityy transformsin el -webkit-prefijo. Actualmente no sé cómo esto afecta la representación de otros navegadores (FF, IE), así que use las versiones no prefijadas con precaución.
sampoh
fuente
27
Podría no haber explicado nada, pero me explicó lo suficiente como para solucionar este problema.
McNab
@Class Stacker: ¿qué explicar? Simplemente copie y pegue el código en su elemento problemático. Por cierto, esto funciona muy bien!
easwee
1
sugiero esta solución stackoverflow.com/a/42256897/1834212 estoy publicando el enlace para evitar la duplicación
Miguel
1
¿Alguien puede confirmar si esto todavía funciona, porque cada vez que agrego `-webkit-backface-visibilidad` y -webkit-transform, realmente no puedo ver un cambio, y cuando abro la consola de desarrollador de chromes. Veo que esas 2 propiedades css se trazan, como si se sobrescribieran, pero no lo están (css y html vacíos). Es como si Chrome ya no los acepta.
Kevin M
1
@KevinM intente sin los prefijos -webkit-, estos ahora son CSS estándar.
Sampoh
91

Debe aplicar la transformación 3D al elemento, para que obtenga su propia capa compuesta. Por ejemplo:

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

o

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

Puede leer más sobre los criterios de creación de capas aquí: Renderizado acelerado en Chrome


Una explicación:

Ejemplos (pasar el cuadro verde):

Cuando usa cualquier transición en su elemento, hace que el navegador recalcule los estilos, luego rediseñe su contenido incluso si la propiedad de transición es visual (en mis ejemplos es una opacidad) y finalmente pinta un elemento:

captura de pantalla

El problema aquí es el rediseño del contenido que puede tener un efecto de elementos "danzantes" o "parpadeantes" en la página mientras ocurre la transición. Si va a la configuración, marque la casilla de verificación "Mostrar capas compuestas" y luego aplique la transformación 3D a un elemento, verá que obtiene su propia capa que se delinea con un borde naranja.

captura de pantalla

Después de que el elemento obtiene su propia capa, el navegador solo necesita componer capas en la transición sin rediseño o incluso operaciones de pintura, por lo que el problema debe resolverse:

captura de pantalla

sol0mka
fuente
¡lindas cosas! obtuve un punto porque de lo detallada que era tu respuesta! ¿Qué software estás usando para capturar / mover la pantalla?
kroe
Spot on mate !! Me ahorró muchas molestias allí.
Esto hizo el truco para mí. Al principio estaba usando translateZ en el padre que estaba animando, pero los sprites de la imagen de fondo todavía estaban borrosos. Estoy usando Velocity.js para escalar otro contenedor dentro de él y apliqué algo como translateZ: 0.000001(algunos # infinitosimales) ¡y listo! ¡Imágenes de fondo nítidas una vez más!
notacouch
Gracias amigo. Esto funcionó en mi problema. Por cierto, mi problema es que tengo un elemento que gira 90 grados y tiene una transición de desvanecimiento usando opacidad. Al activar la transición, el contenido del elemento se mueve 1 px desde la izquierda.
Lloyd aaron
42

Tuve el mismo problema con el iframe embebido de youtube (se usaron traducciones para centrar el elemento iframe). Ninguna de las soluciones anteriores funcionó hasta que intentó restablecer los filtros CSS y sucedió la magia.

Estructura:

<div class="translate">
     <iframe/>
</div>

Estilo [antes]

.translate {
  transform: translateX(-50%);
  -webkit-transform: translateX(-50%);
}

Estilo [después]

.translate {
  transform: translateX(-50%);
  -webkit-transform: translateX(-50%);
  filter: blur(0);
  -webkit-filter: blur(0);
}
xb1itz
fuente
9
filter: blur(0)lo hizo por mi!
Nick
3
Increíble O_o WTF con el desenfoque? ¿Por qué está activado por defecto?
Yuriy Polezhayev
Esta fue la solución para mí también. La respuesta aceptada podría funcionar para las personas que no están utilizando otras funciones de "traducción" en sus propiedades de transformación, pero no me funcionó.
Edward Coyle Jr.
¿No debería -webkit-venir el prefijo antes? Más información
Trevor Nestman
32

Recomiendo un nuevo atributo experimental CSS que probé en el último navegador y es bueno:

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+                */

Con esto, el navegador conocerá el algoritmo para renderizar

Felipez
fuente
Esto solucionó mis imágenes borrosas y rotadas, mientras que la visibilidad de la cara posterior, el desenfoque (0), translateZ no funcionó para mí. Gracias.
Louis Ameline
Las imágenes fijas en algunos casos de uso, lo hicieron peor en otros :-) ¡Interesante en cualquier caso!
Simon Steinberger
Profundizado: image-rendering: -webkit-optimize-contrast;resuelve el problema en Chrome. Sin embargo, las imágenes en otros navegadores, por ejemplo, Firefox, se renderizan mucho, mucho peor con el conjunto de opciones de representación. Por lo tanto, solo uso la directiva WebKit, que también funciona en el motor Blink. ¡Gracias!
Simon Steinberger
En algunos casos, hace que las imágenes sean notablemente irregulares. Parece que no puedo encontrar un punto dulce entre el resultado borroso y este ~ suspiro ~
bigp
4

Acabo de encontrar otra razón por la cual un elemento se vuelve borroso cuando se transforma. Estaba usando transform: translate3d(-5.5px, -18px, 0);para reubicar un elemento una vez que se había cargado, sin embargo, ese elemento se volvió borroso.

Intenté todas las sugerencias anteriores, pero resultó que se debía a que usaba un valor decimal para uno de los valores de traducción. Los números enteros no causan el desenfoque, y cuanto más me alejaba del número entero, peor era el desenfoque.

es decir, 5.5pxdifumina el elemento más, 5.1pxlo menos.

Solo pensé en tirar esto aquí en caso de que ayude a alguien.

Ashrobbins
fuente
Gracias, este fue el problema en mi caso: estaba usando translateY (-50%) que debe haber estado evaluando a un valor de píxel decimal.
b4tch
3

He engañado el problema usando la transición por pasos, no sin problemas

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

No es una solución, es una trampa y no se puede aplicar en todas partes.

No puedo explicarlo, pero funciona para mí. Ninguna de las otras respuestas me ayuda (OSX, Chrome 63, pantalla sin retina).

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

Evgeny Gendel
fuente
En tu violín tiembla como el Parkinson, pero en mi caso funcionó.
Tárcio Zemel
2

Escalar al doble y reducir a la mitad zoomfuncionó para mí.

transform: scale(2);
zoom: 0.5;
Kushagra Gour
fuente
esto parece funcionar en cromo para imágenes. desafortunadamente, también modifica cualquier html que lo haya puesto.
Jack Davidson
2

He probado alrededor de 10 posibles soluciones. Los mezcló y todavía no funcionaban correctamente. Siempre había 1px batido al final.

Encuentro solución reduciendo el tiempo de transición en el filtro.

Esto no funcionó:

.elem {
  filter: blur(0);
  transition: filter 1.2s ease;
}
.elem:hover {
  filter: blur(7px);
}

Solución:

.elem {
  filter: blur(0);
  transition: filter .7s ease;
}
.elem:hover {
  filter: blur(7px);
}

Prueba esto en violín:

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

Espero que esto ayude a alguien.

Adam Orlov
fuente
1

Tratar filter: blur(0);

Funciono para mi

Fred K
fuente
También funcionó para mí, Chrome 63, 64 y Vivaldi 1.13
GTCrais
1

Para mí, ahora en 2018. Lo único que solucionó mi problema (una línea blanca intermitente parpadeante que atraviesa una imagen al pasar el mouse) fue aplicar esto a mi elemento de enlace que contiene el elemento de imagen que tiene 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;
}
mateostabio
fuente
¡Si! 'blur (0)' me lo soluciona en Chrome. Sin embargo, hace que la imagen sea un poco borrosa al cambiar el tamaño, pero es menos notable que el salto / cambio de tamaño
00-BBB
0
filter: blur(0)
transition: filter .3s ease-out
transition-timing-function: steps(3, end) // add this string with steps equal duration

Fui ayudado estableciendo el valor de la duración de la transición .3sigual a los pasos de sincronización.3s

j-tap
fuente
-7

Acabo de tener el mismo problema. Intente establecer la posición: relativa al elemento padre, eso funcionó para mí.

Martín
fuente
55
¿Tienes una demostración de este trabajo? No tengo idea de cómo esto ayudaría
Zach Saucier
2
Si pudiera editar su respuesta y explicar qué hace el código que está mostrando y por qué / cómo ese código responde a la pregunta, realmente podría ayudar. Los bloques de código por sí solos no suelen ser respuestas útiles.
Lea Cohen