web-dev-qa-db-fra.com

L'effet de transition CSS rend l'image floue/déplace l'image 1px, dans Chrome?

Lorsque la div est survolée, un effet de transition CSS la déplace.

Le problème, comme vous pouvez le voir dans l'exemple, est que la transition 'translate' a pour effet horrible de faire en sorte que l'image dans le div se déplace de 1px vers le bas/la droite (et peut-être même légèrement redimensionnée?) De sorte qu'elle apparaisse de lieu et de flou ...

Le pépin semble s’appliquer tout le temps que l’effet de survol est appliqué, et d’un processus d’essais et d’erreur, je peux affirmer avec certitude que cela ne semble se produire que lorsque la transition de translation déplace le div (l’ombre et l’opacité de la boîte sont également appliquées, mais ne font aucune différence) l'erreur une fois enlevé).

2e édition: En fait, le problème n'est PAS résolu!

En créant un JSFiddle pour illustrer le problème, je suis tombé sur une observation intéressante. Le problème ne survient que lorsque la page comporte des barres de défilement. Ainsi, l'exemple avec une seule instance de div est correct, mais une fois de plus, des divs identiques sont ajoutés et la page nécessite par conséquent une barre de défilement. Le problème se pose à nouveau ...

Des idées?!

132
Lewis

Avez-vous essayé cela dansCSS?

.yourDivClass {
    /* ... */

    -webkit-backface-visibility: hidden;
    -webkit-transform: translateZ(0) scale(1.0, 1.0);
}

Cela fait que la division se comporte "plus en 2D".

  • La face arrière est dessinée par défaut pour permettre de retourner des objets avec une rotation Et autres. Cela n’est pas nécessaire si vous vous déplacez uniquement à gauche, à droite, en haut, en bas, à l’échelle ou en rotation.
  • Convertissez l’axe Z pour qu’il ait toujours une valeur nulle.

Modifier

Chrome gère maintenant backface-visibility et transform sans le préfixe -webkit-. Je ne sais pas actuellement comment cela affecte le rendu des autres navigateurs (FF, IE), utilisez donc les versions sans préfixe avec prudence.

232
sampoh

Vous devez appliquer une transformation 3d à l'élément afin qu'il obtienne son propre calque composite . Par exemple:

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

ou

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

Pour en savoir plus sur les critères de création de calques, cliquez ici: Rendu accéléré dans Chrome


Une explication:

Exemples (zone de survol vert): 

Lorsque vous utilisez une transition sur votre élément, le navigateur recalcule les styles, puis remet en forme votre contenu même si la propriété de transition est visuelle (dans mes exemples, il s'agit d'une opacité) et finit par peindre un élément:

screenshot

Le problème ici est la nouvelle présentation du contenu qui peut créer un effet d’éléments "dansants" ou "clignotants" sur la page lorsqu’une transition se produit . appliquer une transformation 3d à un élément, vous verrez qu'il obtient son propre calque délimité par une bordure orange.

screenshot

Une fois que l'élément obtient son propre calque, le navigateur doit simplement composer les calques lors de la transition, sans aucune nouvelle disposition ni même aucune opération de peinture. Le problème doit donc être résolu:

screenshot

85
sol0mka

Avait le même problème avec youtube iframe intégré (Traductions ont été utilisées pour centrer élément iframe). Aucune des solutions ci-dessus n’a fonctionné jusqu’à essayer réinitialiser les filtres css et la magie s’est produite.

Structure:

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

Style [avant]

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

Style [après]

.translate {
  transform: translateX(-50%);
  -webkit-transform: translateX(-50%);
  filter: blur(0);
  -webkit-filter: blur(0);
}
37
xb1itz

J'ai recommandé un nouvel attribut expérimental CSS que j'ai testé sur le dernier navigateur et qui est bon:

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

Avec cela, le navigateur connaît l'algorithme de rendu

30
Felipez

Je viens de trouver une autre raison pour laquelle un élément devient flou lorsqu'il est transformé. J'utilisais transform: translate3d(-5.5px, -18px, 0); pour repositionner un élément une fois chargé, mais cet élément est devenu flou.

J'ai essayé toutes les suggestions ci-dessus, mais il s'est avéré que cela était dû à l'utilisation d'une valeur décimale pour l'une des valeurs de traduction. Les nombres entiers ne causent pas le flou, et plus je m'éloignais du nombre entier, plus le flou devenait pire.

c'est-à-dire 5.5px rend l'élément le plus flou, 5.1px le moins. 

Je pensais juste que je jetterais ceci ici au cas où cela aiderait quelqu'un.

4
ashrobbins

J'ai triché problème en utilisant la transition par étapes, pas en douceur

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

Ce n'est pas une solution, c'est une triche et ne peut pas être appliqué partout.

Je ne peux pas l'expliquer, mais cela fonctionne pour moi. Aucune autre réponse ne m'aide (OSX, Chrome 63, affichage non rétinien).

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

3
Evgeny Gendel

Essayez filter: blur(0); 

Ça a fonctionné pour moi

1
Fred K

Le fait de doubler et de réduire de moitié zoom a fonctionné pour moi.

transform: scale(2);
zoom: 0.5;
1
Kushagra Gour
filter: blur(0)
transition: filter .3s ease-out
transition-timing-function: steps(3, end) // add this string with steps equal duration

On m'a aidé en définissant la valeur de durée de transition .3s étapes de synchronisation égales .3s 

0
j-tap

J'ai essayé environ 10 solutions possibles. Mélangez-les et ils ne fonctionnaient toujours pas correctement. Il y avait toujours 1px shake à la fin.

Je trouve la solution en réduisant le temps de transition sur le filtre.

Cela n'a pas fonctionné:

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

Solution:

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

Essayez ceci en violon:

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

J'espère que ça aidera quelqu'un.

0
Adam Orlov

Pour moi, maintenant en 2018. La seule chose qui résolve mon problème (une ligne blanche scintillante qui scintille dans une image en survol) survient lorsque je l'applique à mon élément de lien contenant l'élément image qui a 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;
}
0
mateostabio