Jak zapobiec zmianie renderowania tekstu w Webkit podczas przejścia CSS

81

Używam przejść CSS do przejścia między stanami przekształconymi CSS (w zasadzie przejście skali elementu). Zauważyłem, że gdy element przechodzi, pozostała część tekstu na stronie (w Webkit) ma tendencję do nieznacznej zmiany renderowania, dopóki przejście nie zostanie zakończone.

Skrzypce: http://jsfiddle.net/russelluresti/UeNFK/

Zauważyłem również, że nie występuje to w moich nagłówkach, które mają -webkit-font-smoothing: antialiasedparę właściwość / wartość. Tak więc, zastanawiam się, czy istnieje sposób, aby tekst zachował swój domyślny wygląd (wartość „auto” dla wygładzania czcionek) i nie zmieniał renderowania podczas przejścia.

Próbowałem jawnie ustawić tekst tak, aby używał wartości „auto”, ale to nic nie daje. Powinienem również zauważyć, że ustawienie wygładzania czcionek na „none” również zapobiega migotaniu renderowania podczas przejścia.

Każda pomoc jest mile widziana.

Edytuj 1

Powinienem zauważyć, że korzystam z systemu OS X. Patrząc na mój test w Chrome na Parallels, nie zauważyłem, że dwa różne akapity zachowują się inaczej, więc może to być problem wyłącznie dla komputerów Mac.

RussellUresti
źródło
21. A wersja Safari to 6. Dzieje się tak w obu przeglądarkach, co sprawia, że ​​myślę, że to Webkit, a nie przeglądarka.
RussellUresti
Zarówno akapity wygładzone, jak i z aliasami zachowują się tak samo. chrome Wersja 23.0.1270.0 canary | 21.0.1180.89 m | 5.17 safari
Zgaduję, że korzystasz z wersji deweloperskiej Chrome. Chociaż system operacyjny może odgrywać w tym rolę. Edytuję pytanie, aby zauważyć, że używam OSX.
RussellUresti
1
Nie mam absolutnie pojęcia, dlaczego to działa, ale dodaję „-webkit-transform: translateZ (0);” do '.antialiased {} wydaje się to naprawić. Działa nawet, jeśli dodasz go do 'p {}'. Ponieważ nie potrafię wyjaśnić, dlaczego to działa, nie czułem się dobrze, aby podać to jako odpowiedź. Mam nadzieję, że to pomoże!
Christofer Vilander,
@Christofer To czyni je spójnymi - ale sprawia, że ​​wszystkie wyglądają na wygładzone (wszystkie są cieńsze). Staram się, aby tekst bez antyaliasingu (pierwszy akapit) pozostał w domyślnym stylu (który wydaje się być nieco pogrubiony niż tekst wygładzony).
RussellUresti

Odpowiedzi:

83

Myślę, że znalazłem rozwiązanie:

-webkit-transform: translateZ(0px);

Wymuszenie akceleracji sprzętowej w elemencie nadrzędnym wydaje się rozwiązywać problem ...

EDYCJA Jak skomentowano, ten hack wyłącza wygładzanie czcionek i może pogorszyć renderowanie tekstu w zależności od czcionek, przeglądarki i systemu operacyjnego!

Armel Larcier
źródło
Wypróbowałem wygładzanie czcionek i nie udało się. Próbowałem tego, zadziałało idealnie
locrizak
Nie dało mi to pożądanego rezultatu w przypadku tego stwierdzonego problemu, ale pomogło to naprawić inne problemy z przejściem CSS, które miałem (takie jak dziwny migający tekst podczas ukrywania / wyświetlania treści w elemencie przejściowym).
RussellUresti
3
Nie działa dla mnie, podczas gdy -webkit-font-smoothing: antyaliasing; i -webkit-backface-visibility: ukryte; Pracuje. Kredyty znajdują się tutaj stackoverflow.com/questions/11589985/…
F Lekschas
+1 super, to jedyna metoda, która zadziałała w sytuacji, w której się znalazłem
Larry
4
W pierwszej kolejności wyłącza to wygładzanie czcionek. Nie ma więc wygładzania czcionki na początku przejścia, bez wygładzania czcionki podczas przejścia i bez wygładzania czcionki na końcu. Nie ma więc zmian w wygładzaniu czcionek, ale także w ogóle bez wygładzania czcionek.
yunzen
45

AKTUALIZACJA Sierpień 2020

Nie musisz już kierować na Safari zapytania o media, aby włączyć wygładzanie czcionek subpikselowych. Domyślnie jest w porządku.

Jednak chociaż domyślnie używa wygładzania czcionek subpikselowych, maść w wygładzaniu czcionek Chrome jest znacząca , dla każdego, kto szuka spójnego renderowania tekstu .

  1. To jest renderowanie jasnego tekstu przez Chrome na ciemnym tle światło w ciemności
  2. To jest renderowanie ciemnego tekstu przez Chrome na jasnym tle ciemno na świetle

Spójrz na rozmiar całości w literze e powyżej. Jasny tekst na ciemnym tle jest renderowany z zauważalnie większą wagą niż ciemny tekst na jasnym tle (z identycznym stylem czcionki CSS).

Jednym z rozwiązań dla witryn, które szanują ustawienia ciemnego / jasnego motywu użytkownika, jest kierowanie na Chrome zapytania o media, które jest ograniczone do trybu ciemnego i przełączenie go na wygładzanie bez subpikseli, jak na przykład:

@media screen
and (-webkit-min-device-pixel-ratio: 0)
and (min-resolution: 0.001dpcm)
and (prefers-color-scheme: dark) {
  body {
    -webkit-font-smoothing: antialiased;
  }
}

Wynik :

ciemno na świetlejasne na ciemnym antyaliasingu

O wiele bardziej spójna waga tekstu, niezależnie od tego, czy renderuje się jasno w ciemności, czy ciemno w świetle.

Zobacz porównanie przed i po: światło w ciemnościjasne na ciemnym antyaliasingu

-

AKTUALIZACJA Maj 2018

-webkit-font-smoothing: subpixel-antialiasedteraz nie działa w Chrome, ale w Safari nadal znacznie poprawia rzeczy, ALE TYLKO W RETINIE. Bez tego w Safari na ekranach siatkówki tekst jest cienki i mdły, podczas gdy z nim tekst ma odpowiednią wagę. Ale jeśli użyjesz tego na wyświetlaczach innych niż Retina w Safari (szczególnie przy niewielkich wartościach wagi) tekst to katastrofa. Zdecydowanie zalecamy użycie zapytania o media:

@media screen and (-webkit-min-device-pixel-ratio: 2) {
  body {
    -webkit-font-smoothing: subpixel-antialiased;
  }
}

Jawne ustawienie -webkit-font-smoothing: subpixel-antialiasedjest najlepszym obecnie rozwiązaniem, jeśli chcesz przynajmniej częściowo uniknąć cieńszego, antyaliasowanego tekstu.

--tl; dr--

Zarówno w przeglądarce Safari, jak i Chrome, w których domyślne renderowanie czcionek wykorzystuje antyaliasing subpikselowy, każdy kod CSS, który wymusza renderowanie oparte na GPU, jak powyższe sugestie dotyczące użycia transformacji przy użyciu translateZ lub nawet tylko przejścia skali, spowoduje, że Safari i Chrome automatycznie „poddadzą się ”na wygładzaniu czcionek z antyaliasem subpikselowym i zamiast tego przełącz się na zwykły antyaliasowany tekst, który wygląda dużo jaśniej i cieńszy, szczególnie w przeglądarce Safari.

Inne reakcje skupiały się na utrzymaniu stałego renderowania, po prostu ustawiając lub wymuszając wygładzanie czcionek w przypadku cieńszego, antyliofilizowanego tekstu. Moim zdaniem użycie translateZ lub backface hidden znacznie obniża jakość renderowania tekstu i jest najlepszym rozwiązaniem, jeśli chcesz, aby tekst pozostał spójny, a cieńszy tekst jest w porządku -webkit-font-smoothing: antialiased. Jednak jawne ustawienie -webkit-font-smoothing: subpixel-antialiasedfaktycznie ma pewien wpływ - tekst nadal nieznacznie się zmienia i jest prawie wyraźnie cieńszy podczas przejść renderowanych na GPU, ale nie tak cienki, jak bez tego ustawienia. Wygląda więc na to, że przynajmniej częściowo zapobiega przełączaniu się na prosty tekst antyliściowy.

bezatomowy
źródło
2
Dzięki za świetną wiadomość!
Denis Gorbaczow
2
To najlepsze rozwiązanie. Wszyscy inni pogarszają renderowanie tekstu, czego OP wyraźnie prosił o unikanie
fregante,
Oszczędza mi życie! Dzięki. Pozwala uniknąć gwałtownego przełączenia na renderowanie subpikselowe po przejściu CSS. Przynajmniej w przypadku przejścia przez krycie utrzymuje to czcionkę włączoną (teoretycznie zawsze domyślnie) renderowanie subpikselowe nawet podczas przejścia. Świetny!
Garavani
najlepsze rozwiązanie dla nas! Dziękuję
kernel
Dzięki, natknąłem się na to ponad rok temu i zapomniałem o tym. To jedyne rozwiązanie, które rozwiązało dla mnie opisywany problem.
Iain Collins
20

Zauważyłem, że prawie za każdym razem, gdy mam problemy z grafiką (migotanie / zacinanie się / przerywanie / itp.) Z powodu przejścia, używając -webkit-backface-visibility: hidden; na elementach, które działają w górę, zwykle rozwiązują problem.

Jordan Borth
źródło
3
To jest (obecnie) poprawna odpowiedź. O ile mi wiadomo, webkit-font-smoothing został usunięty jakiś czas temu, miał zostać dodany ponownie, ale obecnie nie działa u mnie w najnowszej wersji Chrome. Wydaje się, że sztuczka translateZ też już nie działa. Myślę, że w każdej chwili może się to ponownie zmienić. : /
Mantriur
3
To spowodowało, że część tekstu stała się dla mnie niewyraźna.
Jan
8

Aby zapobiec zmianom w renderowaniu tekstu spowodowanym akceleracją sprzętową, możesz:

  1. Ustaw cały tekst na -webkit-font-smoothing: antialiased. Oznacza to, że tekst jest cieńszy i nie ma antyaliasingu podpikselowego.

  2. Jeśli chcesz, aby tekst, na który ma wpływ przyspieszanie sprzętowe, był wygładzany subpikselem (domyślny rodzaj wygładzania czcionki), to umieszczenie tego tekstu wewnątrz wejścia, bez obramowań i wyłączonych, zachowa antyaliasowanie subpikseli (przynajmniej w przeglądarce Chrome w systemie Mac OS X). Nie testowałem tego na innych platformach, ale jeśli antyaliasing subpikselowy jest ważny, możesz przynajmniej użyć tej sztuczki.

Joran Greef
źródło
Przetestowałem opcję 2 (sztuczka z elementem wejściowym) na Win8.1 i Chrome 47 i nie działa.
Paya
3

To właśnie zadziałało dla mnie. Mam nadzieję, że to pomoże. Znaleziono w innym poście stosu overflow.

-webkit-font-smoothing:antialiased;
-webkit-backface-visibility:hidden;
Daniel Almeida
źródło
1

Aby zapobiec zmianie renderowania, musisz ustawić font-smoothing: antialiased(lub none).

Wyłączenie renderowania czcionek subpikselowych przez przeglądarkę jest prawdopodobnie efektem ubocznym przyspieszenia sprzętowego. Gdy tło, na którym renderujesz, stale się przesuwa, tekst nie może być renderowany na osobnej warstwie, ponieważ każda klatka musi być sprawdzona na wszystkich warstwach tła. Może to poważnie obniżyć wydajność.

Apple często wyłącza wygładzanie czcionek subpikselowych we własnych witrynach.

Henrik
źródło
Problem z ustawieniem wygładzania czcionek na antyaliasing polega na tym, że tekst nie wygląda tak, jakbym tego chciał. Chcę uzyskać wizualny efekt ustawienia wygładzania czcionek na „auto” (pogrubiony wygląd) - ale kiedy to zrobisz, tekst przesunie się podczas każdego przejścia. Dlatego moim celem jest po prostu zachowanie odważnego wyglądu „auto” przez cały czas.
RussellUresti
1
Możesz to obejść, nie używając akceleracji sprzętowej. Użyj timera w jQuery i przeprowadź przejście ręcznie (bez przejścia CSS). Nie jestem jednak pewien, czy poleciłbym go, bo wydajność i płynność będą gorsze.
Henrik,
To prawda, mógłbym po prostu użyć jQuery do jego animacji ... To może być jedyne rozwiązanie, jeśli nie ma innego rozwiązania.
RussellUresti
1

Oprócz powyższych rozwiązań ( -webkit-transform: translateZ(0px)w elemencie i -webkit-font-smoothing: antialiasedna stronie) niektóre elementy mogą nadal działać źle. Dla mnie był to tekst zastępczy w elemencie wejściowym: W tym celu użyjposition:relative

WraithKenny
źródło
-1

Miałem ten sam problem. Przeczytaj uważnie:

Zauważyłem, że gdy element przechodzi, pozostała część tekstu na stronie (w Webkit) ma tendencję do nieznacznej zmiany renderowania, dopóki przejście nie zostanie zakończone.

żadne z powyższych rozwiązań nie wydawało się działać. Jednak ustawienie (takie jak)

#myanimation { -webkit-transform: translateZ(0px); }

na elemencie, który ma animację, zadziałał.

Przenosząc animowany element do warstwy GPU, usuwasz go z normalnego przepływu renderowania strony (na przykład rzeczy takie jak indeks z nie będą już działać). Jako efekt uboczny animacja i reszta strony nie będą już na siebie wpływać.

Jeśli ma to wpływ na renderowanie czcionki, robi to oczywiście tylko dla elementu animowanego. Nie widzę różnicy w moim Chrome.

pospolity
źródło
Poprawiono mnie. Widzę zmiany w renderowaniu czcionek w pozostałej części strony, również w miejscach, w których translateZ (0) nie jest stosowane.
commonpike
To jedyna rzecz, która zadziałała, gdy miałem rozmyte ikony czcionek. Zastosowano transformację do animowanych sekcji i rozwiązano problem.
Bill
Koleś, na to odpowiedziano już 2 lata temu. Tuż powyżej ... Dokładna ta sama odpowiedź / kod.
NiCk Newman
tak, moim jedynym celem było to, że musisz umieścić element-webkit-transform na elemencie, który ma animację , aby zapobiec renderowaniu zmian na innych elementach na stronie . ale jak skomentowałem, działało to przez chwilę i przestało działać, gdy później zmieniłem fragmenty strony.
Commonpike