Как предотвратить изменение рендеринга текста Webkit при переходе через CSS

81

Я использую переходы CSS для перехода между преобразованными состояниями CSS (в основном изменяя масштаб элемента). Я замечаю, что при переходе элемента остальной текст на странице (в Webkit) имеет тенденцию немного изменять его отображение, пока переход не будет выполнен.

Сценарий: http://jsfiddle.net/russelluresti/UeNFK/

Я также заметил, что этого не происходит с моими заголовками, которые имеют -webkit-font-smoothing: antialiased пара свойство / значение. Итак, мне интересно, есть ли способ сохранить вид текста по умолчанию (значение «auto» для сглаживания шрифта) и не изменять рендеринг во время перехода.

Я пробовал явно установить в тексте значение «авто», но это ничего не дает. Я также должен отметить, что установка сглаживания шрифта на «none» также предотвращает мигание рендеринга во время перехода.

Любая помощь приветствуется.

Редактировать 1

Я должен отметить, что я использую OS X. Просматривая свой тест в Chrome на Parallels, я не заметил, что два разных абзаца ведут себя по-разному, так что это может быть проблемой исключительно для Mac.

Рассел Урести
источник
21. И версия Safari - 6. Это происходит в обоих браузерах, поэтому я думаю, что это Webkit, а не браузер.
RussellUresti
абзацы со сглаживанием и псевдонимом демонстрируют одинаковое поведение. chrome Версия 23.0.1270.0 канарейка | 21.0.1180.89 м | 5.17 safari
Я предполагаю, что вы используете версию Chrome для разработчиков. Хотя ОС может сыграть в этом свою роль. Я отредактирую вопрос, чтобы отметить, что я использую OSX.
RussellUresti
1
Я понятия не имею, почему это работает, но добавляю '-webkit-transform: translateZ (0);' to '.antialiased {}, похоже, это исправляет. Это даже работает, если вы добавите его в 'p {}'. Поскольку я не могу объяснить, почему это работает, я считаю неправильным давать его в качестве ответа. Надеюсь, это поможет!
Christofer Vilander
@Christofer Это делает их согласованными, но заставляет их все выглядеть сглаженными (все они более тонкий текст). Я пытаюсь сделать так, чтобы текст без сглаживания (первый абзац) оставался в стиле по умолчанию (который выглядит немного более жирным, чем текст со сглаживанием).
RussellUresti

Ответы:

83

Думаю, я нашел решение:

-webkit-transform: translateZ(0px);

Похоже, что принудительное аппаратное ускорение родительского элемента решает проблему ...

ИЗМЕНИТЬ Как уже отмечалось, этот хак отключает сглаживание шрифтов и может ухудшить рендеринг текста в зависимости от ваших шрифтов, браузера и ОС!

Армель Ларсье
источник
Пробовал сглаживание шрифтов, и это не сработало. Попробовал, отлично сработало
locrizak
Это не дало мне желаемого результата для указанной проблемы, но помогло исправить другие проблемы с переходом CSS, которые у меня были (например, странно мигающий текст при скрытии / отображении содержимого внутри переходного элемента).
RussellUresti
3
У меня не работает, тогда как -webkit-font-smoothing: antialiased; и -webkit-backface-visibility: скрыто; работает. Кредиты можно найти здесь stackoverflow.com/questions/11589985/…
F Lekschas 03
+1 круто, это единственный метод, который сработал в той ситуации, в которой я оказался
Ларри
4
Это в первую очередь отключает сглаживание шрифтов. Таким образом, у вас нет сглаживания шрифтов в начале перехода, сглаживания шрифтов при переходе и сглаживания шрифтов в конце. Так что никакого сглаживания шрифтов, но и никакого сглаживания шрифтов.
yunzen
45

ОБНОВЛЕНИЕ Август 2020

Вам больше не нужно настраивать Safari с помощью медиа-запроса, чтобы включить субпиксельное сглаживание шрифтов. По умолчанию все в порядке.

Однако , хотя по умолчанию он использует субпиксельное сглаживание шрифтов, сглаживание шрифтов в Chrome - это значительная ложка дегтя для всех, кто ищет единообразное отображение текста .

  1. Это рендеринг светлого текста на темном фоне в Chrome. свет на темноте
  2. Это рендеринг темного текста на светлом фоне в Chrome. темно на свете

Посмотрите на размер целого на букву е выше. Светлый текст на темном фоне визуализируется с заметно более тяжелым весом, чем темный текст на светлом фоне (с идентичным стилем шрифта css).

Одно из решений для сайтов, соблюдающих настройку темной / светлой темы пользователя, - настроить таргетинг на Chrome медиа-запросом, который ограничен темным режимом, и переключить его на сглаживание без субпикселей, например:

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

Результат :

темно на светесвет на темный сглаживание

Гораздо более стабильный вес текста независимо от того, отображает ли он свет на темном или темный на светлом.

Посмотрите параллельное сравнение до и после: свет на темнотесвет на темный сглаживание

-

ОБНОВЛЕНИЕ Май 2018

-webkit-font-smoothing: subpixel-antialiasedтеперь не действует в Chrome, но в Safari он все еще значительно улучшает ситуацию, НО ТОЛЬКО В RETINA. Без него в Safari на экранах Retina текст будет тонким и безвкусным, тогда как с ним текст имеет надлежащий вес. Но если вы используете это на дисплеях без сетчатки в Safari, текст (особенно при небольших значениях веса) станет катастрофой. Настоятельно рекомендую использовать медиа-запрос:

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

Явная установка -webkit-font-smoothing: subpixel-antialiased - лучшее текущее решение, если вы хотите хотя бы частично избежать более тонкого сглаженного текста.

--tl; dr--

И в Safari, и в Chrome, где рендеринг шрифтов по умолчанию использует субпиксельное сглаживание, любой CSS, который заставляет рендеринг на основе графического процессора, как приведенные выше предложения использовать преобразование с использованием translateZ или даже просто масштабный переход, приведет к тому, что Safari и Chrome автоматически «откажутся» "при сглаживании шрифтов с субпиксельным сглаживанием и вместо этого переключитесь на текст с субпиксельным сглаживанием, который выглядит намного светлее и тоньше, особенно в Safari.

Другие ответы были сосредоточены на поддержании постоянного рендеринга путем простой установки или принудительного сглаживания шрифта для более тонкого сглаженного текста. На мой взгляд, использование translateZ или backface hidden значительно ухудшает качество рендеринга текста, и лучшее решение, если вы хотите, чтобы текст оставался последовательным, и вы в порядке с более тонким текстом, просто использовать -webkit-font-smoothing: antialiased. Однако явная настройка -webkit-font-smoothing: subpixel-antialiasedдействительно имеет некоторый эффект - текст по-прежнему немного меняется и становится заметно тоньше во время переходов, отображаемых на графическом процессоре, но не таким тонким, как без этого параметра. Так что, похоже, это хотя бы частично препятствует переходу на прямой сглаженный текст.

безатомный
источник
2
Спасибо за отличную запись!
Денис Горбачев
2
Это лучшее решение. Все остальные ухудшают рендеринг текста, чего OP специально просил избегать
fregante
Спаситель для меня! Благодарю. Избегает резкого переключения на рендеринг субпикселей после перехода css. По крайней мере, с переходом непрозрачности это сохраняет шрифт (теоретически всегда по умолчанию) субпиксельного рендеринга даже во время перехода. Большой!
Garavani
лучшее решение для нас! Спасибо
ядро
Спасибо, я наткнулся на это больше года назад и забыл об этом. Это единственное решение, которое помогло мне решить описанную проблему.
Иэн Коллинз
20

Я заметил, что почти каждый раз, когда у меня возникают проблемы с графикой (мерцание / заикание / волнение и т. Д.) Из-за перехода с использованием -webkit-backface-visibility: hidden; на элементы, которые действуют, имеет тенденцию решать проблему.

Джордан Борт
источник
3
Это (на данный момент) правильный ответ. Насколько мне известно, webkit-font-smoothing был удален некоторое время назад, должен был быть добавлен снова, но в настоящее время не работает для меня в последней версии Chrome. Трюк translateZ, похоже, тоже больше не работает. Думаю, это может снова измениться в любой момент. : /
Mantriur
3
Из-за этого текст стал для меня размытым.
Джон
8

Чтобы предотвратить изменения отрисовки текста из-за аппаратного ускорения, вы можете:

  1. Установите для всего текста значение -webkit-font-smoothing: antialiased. Это означает, что текст тоньше и не имеет субпиксельного сглаживания.

  2. Если вы хотите, чтобы текст, на который влияет аппаратное ускорение, подвергался субпиксельному сглаживанию (тип сглаживания шрифтов по умолчанию), то размещение этого текста во входных данных без границ и отключение сохранит этот субпиксельный антиалиасинг (по крайней мере, в Chrome в Mac OS X). Я не тестировал это на других платформах, но если субпиксельное сглаживание важно, вы можете хотя бы использовать этот трюк.

Йоран Гриф
источник
Я тестировал вариант 2 (трюк с элементом ввода) на Win8.1 и Chrome 47, и он не работает.
Пайя
3

Это то, что у меня сработало. Надеюсь, поможет. Найдено в другом сообщении stackoverflow.

-webkit-font-smoothing:antialiased;
-webkit-backface-visibility:hidden;
Даниэль Алмейда
источник
1

Чтобы предотвратить изменение рендеринга необходимо установить font-smoothing: antialiased(или none).

Браузер, отключающий рендеринг субпиксельных шрифтов, вероятно, является побочным эффектом аппаратного ускорения. Когда фон, на котором выполняется рендеринг, постоянно смещается, текст не может быть отображен на отдельном слое, поскольку каждый кадр должен проверяться на всех фоновых слоях. Это может серьезно снизить производительность.

Apple , часто отключают субпиксель шрифта сглаживающий на своих собственных сайтах.

Хенрик
источник
Проблема с установкой сглаживания шрифта на сглаживание заключается в том, что текст выглядит не так, как я хочу. Мне нужен визуальный эффект установки сглаживания шрифта на «авто» (более жирный вид) - но когда вы это сделаете, текст будет сдвигаться во время любого перехода. Итак, моя цель - всегда сохранять смелый вид «авто».
RussellUresti,
1
Вы можете обойти это, не используя аппаратное ускорение. Используйте таймер в jQuery и выполните переход вручную (без перехода CSS). Я не уверен, что рекомендовал бы его, так как производительность и плавность будут хуже.
Хенрик,
Правда, я мог бы просто использовать jQuery для его анимации ... Это может быть единственное решение, если другого решения нет.
RussellUresti
1

В дополнение к вышеуказанным решениям ( -webkit-transform: translateZ(0px)в элементе и -webkit-font-smoothing: antialiasedна странице) некоторые элементы могут по-прежнему работать плохо. Для меня это был текст-заполнитель в элементе ввода: для этого используйтеposition:relative

WraithKenny
источник
-1

У меня такая же проблема. Прочтите внимательно:

Я замечаю, что при переходе элемента остальной текст на странице (в Webkit) имеет тенденцию немного изменять его отображение, пока переход не будет выполнен.

ни одно из вышеперечисленных решений, похоже, не сработало. Однако установка (например,)

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

на элементе с анимацией .

Перенося анимированный элемент на уровень графического процессора, вы выводите его из обычного потока рендеринга страницы (например, такие вещи, как z-index, тоже больше не будут работать). В качестве побочного эффекта анимация и остальная часть страницы больше не будут влиять друг на друга.

Если это влияет на рендеринг вашего шрифта, то, конечно, это касается только анимированного элемента. Я не вижу разницы в своем Chrome.

обыкновенная пика
источник
Я исправился. Я вижу изменения в рендеринге шрифтов на остальной части страницы, а также там, где не применяется translateZ (0).
commonpike
Это единственное, что у меня работало, когда значки шрифтов становились размытыми. Применил преобразование к анимируемым разделам и решил проблему.
Билл
Чувак, на это уже ответили 2 года назад. Прямо вверху ... Точно такой же ответ / код.
NiCk Newman
да, единственное, что я хотел сказать, это то, что вы должны поставить -webkit-transformна элемент, который имеет анимацию , чтобы предотвратить изменения рендеринга других элементов на странице . но, как отмечалось, он работал некоторое время и перестал работать, когда я позже изменил биты страницы.
commonpike