CSS-Übergangseffekt macht Bild verschwommen / verschiebt Bild 1px, in Chrome?

150

Ich habe einige CSS, bei denen beim Schweben ein CSS-Übergangseffekt ein Div bewegt.

Das Problem ist, wie Sie im Beispiel sehen können, dass der translateÜbergang den schrecklichen Nebeneffekt hat, dass sich das Bild im Div um 1 Pixel nach unten / rechts bewegt (und möglicherweise die Größe geringfügig ändert?), So dass es fehl am Platz erscheint und unscharf...

Der Fehler scheint die ganze Zeit über zu wirken, wenn der Hover-Effekt angewendet wird, und aus einem Prozess von Versuch und Irrtum kann ich mit Sicherheit sagen, dass er nur dann auftritt, wenn der Übersetzungsübergang das Div verschiebt (Kastenschatten und Deckkraft werden ebenfalls angewendet, machen aber keinen Unterschied zu der Fehler beim Entfernen).

Das Problem scheint nur aufzutreten, wenn die Seite Bildlaufleisten enthält. Das Beispiel mit nur einer Instanz des Div ist in Ordnung, aber sobald wieder identische Divs hinzugefügt werden und die Seite daher eine Bildlaufleiste erfordert, tritt das Problem erneut auf ...

Lewis
quelle
1
Ich bin auf Chrome 27 unter OSX und es ist in Ordnung. Ich glaube, wenn der Inhalt in eine Ebene eingefügt wird, wird er während der Animation in eine Bitmap umgewandelt, und bei älteren Versionen / älteren Grafikkarten sieht dies nicht besonders gut aus. Versuchen Sie eine neuere Version und prüfen Sie, ob sie behoben ist.
Rich Bradshaw
Alles in Ordnung unter Chrome 25 OS X. Übrigens: Ich würde einen anderen Ansatz für die Hintergrundgradiententextur vorschlagen als ein 300-KB-Bild!
Paolo
Und danke @Paolo - das Hintergrundbild war nur für die Demonstration gedacht, es ist nicht das Bild, das auf der tatsächlichen Site verwendet wird!
Lewis
2
Das Problem tritt auf, wenn die Animation von der GPU verarbeitet wird. Es sieht so aus, als ob die Bitmap-Rundungen etwas abweichen. Wird in Canary reproduziert, aber es funktioniert in Ordnung, wenn Sie die GPU-Beschleunigung ausschalten
vals
Sie können diese Lösung für jeden Frame ausprobieren
Miguel

Antworten:

247

Update 2020

  • Wenn Sie Probleme mit verschwommenen Bildern haben, überprüfen Sie auch die Antworten von unten, insbesondere die image-renderingCSS-Eigenschaft.
  • Aus Gründen der Barrierefreiheit und der Suchmaschinenoptimierung können Sie das Hintergrundbild <img>mithilfe der objektangepassten CSS-Eigenschaft durch ein Tag ersetzen .

Ursprüngliche Antwort

Versuchen Sie dies in Ihrem CSS :

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

Dies bewirkt, dass sich die Division "mehr 2D" verhält.

  • Die Rückseite wird standardmäßig gezeichnet, um das Umdrehen von Objekten mit Drehen und dergleichen zu ermöglichen. Dies ist nicht erforderlich, wenn Sie sich nur nach links, rechts, oben, unten, skalieren oder (gegen) den Uhrzeigersinn drehen.
  • Verschieben Sie die Z-Achse so, dass sie immer einen Nullwert hat.
  • Chrome verarbeitet jetzt backface-visibilityund transformohne -webkit-Präfix. Ich weiß derzeit nicht, wie sich dies auf das Rendern anderer Browser (FF, IE) auswirkt. Verwenden Sie daher die Versionen ohne Präfix mit Vorsicht.
Sampoh
quelle
27
Hätte nichts erklären können, aber es hat genug erklärt, um dieses Problem für mich zu beheben.
McNab
@ Class Stacker - was ist zu erklären? Sie kopieren einfach den Code und fügen ihn in Ihr problematisches Element ein. Übrigens funktioniert das sehr gut!
Easwee
1
Ich schlage vor, diese Lösung stackoverflow.com/a/42256897/1834212 Ich poste den Link, um Doppelarbeit zu vermeiden
Miguel
1
Kann jemand bestätigen, ob dies noch funktioniert, denn wenn ich "-webkit-backface-sichtbarkeit" hinzufüge und -webkit-transform, kann ich keine Änderung wirklich sehen und wenn ich die Chromes-Entwicklerkonsole öffne. Ich sehe, dass diese 2 CSS-Eigenschaften durchgestrichen werden, als ob sie überschrieben würden, aber sie sind es nicht (leeres CSS und HTML). Es ist, als würde Chrom sie nicht mehr akzeptieren.
Kevin M
1
@ KevinM versuchen ohne die -webkit- Präfixe, diese sind jetzt Standard-CSS.
Sampoh
91

Sie müssen eine 3D-Transformation auf das Element anwenden, damit es eine eigene zusammengesetzte Ebene erhält. Zum Beispiel:

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

oder

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

Weitere Informationen zu Layer-Erstellungskriterien finden Sie hier: Beschleunigtes Rendern in Chrome


Eine Erklärung:

Beispiele (Hover Green Box):

Wenn Sie einen Übergang für Ihr Element verwenden, berechnet der Browser die Stile neu. Layouten Sie dann Ihren Inhalt neu, auch wenn die Übergangseigenschaft visuell ist (in meinen Beispielen ist es eine Deckkraft), und malen Sie schließlich ein Element:

Bildschirmfoto

Hier geht es um ein neues Layout des Inhalts, das dazu führen kann, dass während des Übergangs Elemente auf der Seite "tanzen" oder "blinken". Wenn Sie zu den Einstellungen gehen, das Kontrollkästchen "Zusammengesetzte Ebenen anzeigen" aktivieren und dann eine 3D-Transformation auf ein Element anwenden, sehen Sie, dass es eine eigene Ebene erhält, die mit einem orangefarbenen Rand umrandet ist.

Bildschirmfoto

Nachdem das Element eine eigene Ebene erhalten hat, muss der Browser beim Übergang nur noch Ebenen zusammensetzen, ohne sie neu zu gestalten oder zu malen. Daher muss das Problem gelöst werden:

Bildschirmfoto

sol0mka
quelle
gutes Zeug! Ich habe einen Punkt dafür, wie detailliert Ihre Antwort war! Welche Software verwenden Sie für die Bildschirmaufnahme / Pfeilerstellung?
Kroe
Genau richtig, Kumpel !! Hat mir dort viel Ärger erspart.
Das hat den Trick für mich getan. Zuerst habe ich translateZ für das übergeordnete Element verwendet, das ich animiert habe, aber die darin enthaltenen Hintergrundbild-Sprites waren immer noch verschwommen. Ich benutze Velocity.js, um einen weiteren Container darin zu skalieren und etwas wie translateZ: 0.000001(ein infinitesimales #) und voila anzuwenden! Wieder scharfe Hintergrundbilder!
Notacouch
Danke Kumpel. Das hat bei meinem Problem funktioniert. Mein Problem ist übrigens, dass ich ein Element habe, das um 90 Grad gedreht ist und einen Einblendübergang mit Deckkraft hat. Beim Auslösen des Übergangs wird der Inhalt des Elements um 1 Pixel von links verschoben.
Lloyd Aaron
42

Hatte das gleiche Problem mit eingebettetem YouTube-Iframe (Übersetzungen wurden zum Zentrieren des Iframe-Elements verwendet). Keine der oben genannten Lösungen funktionierte, bis versucht wurde, CSS-Filter zurückzusetzen und Magie auftrat.

Struktur:

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

Stil [vorher]

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

Stil [nach]

.translate {
  transform: translateX(-50%);
  -webkit-transform: translateX(-50%);
  filter: blur(0);
  -webkit-filter: blur(0);
}
xb1itz
quelle
9
filter: blur(0)habe es für mich getan!
Nick
3
Unglaubliche O_o WTF mit der Unschärfe? Warum ist es standardmäßig aktiviert?
Yuriy Polezhayev
Dies war auch für mich die Lösung. Die akzeptierte Antwort könnte für Personen funktionieren, die keine anderen "Übersetzungs" -Funktionen in ihren Transformationseigenschaften verwenden, aber für mich nicht.
Edward Coyle Jr.
Sollte das -webkit-Präfix nicht vorher kommen? Weitere
Informationen
32

Ich habe ein experimentelles neues Attribut CSS empfohlen, das ich mit dem neuesten Browser getestet habe, und es ist gut:

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

Damit kennt der Browser den Algorithmus zum Rendern

Felipez
quelle
Dadurch wurden meine verschwommenen, gedrehten Bilder behoben, während die Sichtbarkeit der Rückseite, Unschärfe (0), translateZ bei mir nicht funktionierte. Danke dir.
Louis Ameline
In einigen Anwendungsfällen wurden Bilder behoben, in anderen wurde es schrecklich schlimmer :-) Auf jeden Fall interessant!
Simon Steinberger
Tiefer eingegraben: Behebt image-rendering: -webkit-optimize-contrast;das Problem in Chrome. Bilder in anderen Browsern, z. B. Firefox, werden jedoch mit der festgelegten Renderoption viel, viel schlechter gerendert. Daher verwende ich nur die WebKit-Direktive, die auch auf der Blink-Engine funktioniert. Vielen Dank!
Simon Steinberger
In einigen Fällen sind die Bilder merklich zackig. Ich kann keinen Sweet-Spot zwischen dem verschwommenen Ergebnis und diesem finden ~
seufz
4

Ich habe gerade einen anderen Grund gefunden, warum ein Element bei der Transformation verschwimmt. Ich habe transform: translate3d(-5.5px, -18px, 0);ein Element neu positioniert, nachdem es geladen wurde, aber dieses Element wurde verschwommen.

Ich habe alle oben genannten Vorschläge ausprobiert, aber es stellte sich heraus, dass ich einen Dezimalwert für einen der Übersetzungswerte verwendet habe. Ganze Zahlen verursachen keine Unschärfe, und je weiter ich von der ganzen Zahl entfernt war, desto schlimmer wurde die Unschärfe.

dh 5.5pxverwischt das Element am meisten, 5.1pxam wenigsten.

Ich dachte nur, ich würde das hier schmeißen, falls es jemandem hilft.

Aschenbecher
quelle
Vielen Dank, dies war das Problem in meinem Fall - ich habe translateY (-50%) verwendet, das auf einen dezimalen Pixelwert ausgewertet werden muss.
b4tch
3

Ich habe das Problem mit dem schrittweisen Übergang betrogen, nicht reibungslos

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

Es ist keine Lösung, es ist ein Betrug und kann nicht überall angewendet werden.

Ich kann es nicht erklären, aber es funktioniert für mich. Keine andere Antwort hilft mir (OSX, Chrome 63, Non-Retina-Display).

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

Evgeny Gendel
quelle
In deiner Geige zittert es wie bei Parkinson, aber in meinem Fall hat es funktioniert.
Tárcio Zemel
2

zoomFür mich hat es funktioniert, auf das Doppelte zu skalieren und es auf die Hälfte zu reduzieren.

transform: scale(2);
zoom: 0.5;
Kushagra Gour
quelle
Dies scheint in Chrom für Bilder zu funktionieren. Leider ändert es auch jedes HTML, das Sie es auch setzen.
Jack Davidson
2

Ich habe ungefähr 10 mögliche Lösungen ausprobiert. Verwechselt sie und sie funktionierten immer noch nicht richtig. Am Ende gab es immer 1px Shake.

Ich finde eine Lösung, indem ich die Übergangszeit am Filter reduziere.

Das hat nicht funktioniert:

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

Lösung:

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

Versuchen Sie dies in Geige:

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

Ich hoffe das hilft jemandem.

Adam Orlov
quelle
1

Versuchen filter: blur(0);

Es hat bei mir funktioniert

Fred K.
quelle
Arbeitete auch für mich, Chrome 63, 64 und Vivaldi 1.13
GTCrais
1

Für mich jetzt im Jahr 2018. Das einzige, was mein Problem behoben hat (eine weiße Glitchy-Flicker-Linie, die beim Schweben durch ein Bild verläuft), war, dies auf mein Link-Element anzuwenden, das das Bildelement enthält, das es hat 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
quelle
Ja! 'blur (0)' behebt es für mich in Chrome. Macht das Bild beim Ändern der Größe sehr leicht verschwommen, ist aber weniger auffällig als das Springen / Ändern der Größe
00-BBB
0
filter: blur(0)
transition: filter .3s ease-out
transition-timing-function: steps(3, end) // add this string with steps equal duration

Mir wurde geholfen, indem ich den Wert der Übergangsdauer .3sgleich den Übergangszeitschritten einstellte.3s

j-tippen
quelle
-7

Habe gerade das gleiche Problem. Versuchen Sie, die Position festzulegen: relativ zum übergeordneten Element, das bei mir funktioniert hat.

Martin
quelle
5
Haben Sie eine Demo dieser Arbeit? Ich habe keine Ahnung, wie das helfen würde
Zach Saucier
2
Wenn Sie bitte Ihre Antwort bearbeiten und erklären könnten, was der angezeigte Code bewirkt und warum / wie dieser Code die Frage beantwortet, könnte dies wirklich helfen. Codeblöcke allein sind normalerweise keine nützlichen Antworten.
Lea Cohen