Главная » Css live » Стандарт для нестандартного

Стандарт для нестандартного

Стандарты, увы,  не всегда поспевают за нашими потребностями. Иногда соблазн быстро решить задачу одной-двумя нестандартными строчками бывает слишком велик. Особенно если по этой строчке не видно, что она нестандартная. Когда-то давно, в эпоху префиксов, некоторые браузеры любили выпускать свою отсебятину под видом экспериментальных новинок — авось никто разбираться не будет. А в самых запущенных случаях браузеры и вовсе годами тихо саботируют стандарт, принятый остальными, не оставляя разработчикам другого выбора.

В какой-то момент оказалось, что такими нестандартными штуками в вебе достаточно активно пользуются. И бедным браузерам, чтобы не вылететь из конкурентной гонки, волей-неволей пришлось худо-бедно эту отсебятину поддерживать. Фактически, она стала стандартом де-факто. И практикам из WHATWG ничего не осталось, как написать для этих нестандартных штук свой стандарт, названный стандартом совместимости (Compatibility Standard). Чем же он нас порадует?

-webkit-всё-подряд

Первое, что бросается в глаза, на каком месте ни раскрой эту спецификацию — обилие префикса -webkit-. Он и в @-директивах (напр. @keyframes), и в медиавыражениях, и в CSS-свойствах, и в DOM API… Всё верно: стандарт совместимости предписывает браузерам понимать записи с чужим браузерным префиксом. Так поневоле исторически сложилось. Одно время слишком многие веб-разработчики чересчур увлекались экспериментальными новинками за префиксом -webkit-. Особенно за рубежом, где идеи веб-стандартов продвигали не так активно. Так что на всякий случай не полагайтесь на префикс -webkit- как хак, чтобы какой-то код сработал только в WebKit-браузерах: это уже так не работает, браузеры давно стали «всеядными». И это стандарт.

Чаще всего по стандарту совместимости записи с префиксом -webkit- должны считаться просто псевдонимом, «алиасом» для нормальных, беспрефиксных CSS-записей. Это касается директивы @keyframes и целой кучи CSS-свойств, прежде всего относящихся к CSS-трансформациям, анимациям и флексбоксам (в общем, почти всему тому, что когда-то давно называлось звучным словом «CSS3»). Но есть некоторые исключения и нюансы.

Старые градиенты

Стандарт совместимости предписывает браузерам понимать префикс -webkit- для CSS-градиентов — линейных и радиальных, обычных и повторяющихся (-repeating-). Но здесь нюанс: они соответствуют не современной редакции спецификации градиентов, а архивной редакции 2011 г. Без ключевого слова to и «волшебных углов». Так что браузеры теперь вынуждены тащить старый движок градиентов в придачу к новому. Это, конечно, не повод пользоваться старым вместо нового. Но это напоминание о цене изменений в вебе, особенно для чего-то, уже массово внедренного. Будем надеяться, что рабочая группа CSS извлекла из этой истории урок.

Проверка на «ретину»

Казалось бы, CSS-медиавыражения — давно стандарт (рекомендация W3C, самый зрелый статус). В том числе проверка разрешения экрана (min-/max-resolution). Но один браузер (Safari) почему-то уже много лет не торопится выпускать поддержку стандартного синтаксиса resolution из-за флага. Из-за этого приходится использовать стандартный синтаксис параллельно со старым -webkit-device-pixel-ratio, совсем как давным-давно.

Стандарт совместимости предписывает, чтобы браузеры воспринимали -webkit-device-pixel-ratio как псевдоним для resolution, со значением в единицах dppx («точек экрана на CSS-пиксель»). Так что, теоретически, можно обойтись одним нестандартным -webkit-device-pixel-ratio и рассчитывать, что все браузеры его поймут. Хотя лично я бы не рисковал:)

Заливка и обводка для текста

Дизайнеры любят эффектные заголовки, где контуры букв залиты градиентом или другой картинкой. Когда-то единственным способом сверстать это была картинка. Уже давно это можно кроссбраузерно сделать встроенным SVG с элементом <text>, к которому применимы все SVG-шные (и многие СSS-ные) украшения, при этом он остается выделяемым и копируемым текстом. В современном CSS есть и еще более удобные решения этой задачи. Но часто хочется чего-нибудь «попроще и побыстрее»… Лет 10 назад Apple втихаря добавили такой соблазн, и он стал так популярен, что попал в стандарт совместимости.

Соблазн «маскируется» под стандартное CSS-свойство background-clip: вдобавок к трем стандартным значениям коварные искусители с яблоком добавили для своей префикснутой версии четвертое — text. Оно обрезает фон по контуру символов текста. Т.е. выделяет заливку для переднего плана (англ. «Foreground»), действуя через задний план (англ. «Background»). Заголовок соотв. раздела стандарта совместимости — для англоговорящих он выглядит как «Обрезка текста переднего плана: свойство “обрезка-заднего-плана”» — наглядно подчеркивает эту нелогичность.

Неудивительно, что официальные стандарты долго и упорно сопротивлялись странному «нововведению», и даже в черновике фонов и границ 4 уровня это значение пока под большим вопросом. Но все современные браузеры поддерживают его (с префиксом). Так что сегодня -webkit-background-clip: text — решение не только простое, но и достаточно кроссбраузерное.

Одна проблема: фона, обрезанного по границам текста, не видно за цветом самого текста. И по сей день в сети встречаются примеры самого «очевидного» и «лобового» решения этой проблемы (например, на CSS-Tricks):

color:transparent (сделать текст невидимым)

Не надо так. Не надо делать текст по умолчанию невидимым везде, чтобы потом браузер, может быть, если повезет, применил какую-то магию и опять «проявил» его. Невидимый текст вызывает подозрения, что его пытались спрятать, а это не любят поисковики. Да и пользователи IE и Оперы Мини имеют право хотя бы прочитать тот заголовок. Не убивайте текст, пожалуйста!

Лучше пусть старый добрый color у текста останется неизменным и служит надежным фолбэком, а заодно индикатором того, что вы ни от кого его не прячете. А чтобы заливка текста не мешала показу фона, используйте специальное свойство из того же стандарта совместимости: -webkit-text-fill-color. Оно работает в тех же самых браузерах, что и -webkit-background-clip: text. У него приоритет перед color, а значение по умолчанию —currentColor (текущее значение color), поэтому по умолчанию его действие незаметно, но его легко переопределить. Так что в старых браузерах сработает обычный color и пользователи увидят обычный текст. А в браузерах, поддерживающих стандарт совместимости, -webkit-text-fill-color: transparent получит приоритет над color, и пользователи увидят фон, красиво обрезанный по контуру букв благодаря -webkit-background-clip: text:

See the Pen BPXzrM by Ilya Streltsyn (@SelenIT) on CodePen.

Кстати, при виде свойства для заливки текста у меня давно возникает вопрос: что мешало добавить к -webkit-text-fill-color еще и -webkit-text-fill-image — и заливать текст картинкой не через задни…й план, а напрямую, явно? Были бы два похожих, но независимых набора свойств — один для заднего плана (background-*), другой для переднего (text-fill-*). Разве не логичнее? На вопрос, почему так не сделали сразу, мне приводили аргументы про сложности с очередностью отрисовки теней и т.п., но меня они пока не убедили. Может, вы убедите меня в комментариях?

Пока же необходимость вынужденного сосуществования стандартного background-clip и «стандартно нестандартного» -webkit-background-clip: text вынуждает постоянно быть начеку: ведь где сложность, там и баги. Например, Firefox впадает в панику, когда к одному элементу нужно применить несколько фонов, один из которых обрезан по тексту (спасибо за бдительность Ане Тюдор). Даже фолбэк в этой ситуации не спасает.

Чтобы текст эффектного заголовка оставался читаемым при любом раскладе, можно воспользоваться еще одним свойством из того же раздела того же стандарта совместимости (и с той же браузерной поддержкой): -webkit-text-stroke. Оно — сокращение для двух подсвойств, -webkit-text-stroke-width и -webkit-text-stroke-color, и принимает соответственно толщину и цвет обводки контура символов. Лучше, конечно, обсудить это с дизайнером — вдруг он просто «не знал, что так можно» и сам с радостью ухватится за эту идею. Но во многих случаях, думаю, если большому картиночному заголовку добавить что-то типа -webkit-text-stroke: .5px rgba(0,0,0,.2), ничьи эстетические чувства особо не пострадают: да, граница текста будет выглядеть чуть контрастнее, но это можно даже считать плюсом. Зато если картинка по какой-то причине не загрузилась или не обрезалась, как надо, можно будет хоть контуры букв разглядеть.

See the Pen WKVxLe by Ilya Streltsyn (@SelenIT) on CodePen.

В общем, если уж делать градиентный/графический текст нестандартными средствами — давайте хотя бы делать это по стандарту для нестандартного, используя всю его мощь! 🙂

Хорошая новость

Как и все стандарты WHATWG, стандарт совместимости — это «живой стандарт», постоянно обновляемый и всегда актуальный на текущий момент. Если присмотреться к нему, можно заметить, что когда-то этот список вынужденно поддерживаемой нестандартщины был больше, чем теперь. Например, целый раздел «Интерфейс WebKitCSSMatrix» сейчас состоит из единственного примечания:

Примечание: WebKitCSSMatrix теперь определяется спецификацией DOM Geometry. [geometry-1].

Ссылка ведет на отдельный модуль геометрических интерфейсов 1 уровня — совместное детище рабочих групп CSS и SVG, описывающее DOM-интерфейсы для всяких геометрических трансформаций над точками и фигурами, в том числе страшные матрицы. В нем сказано, что старый нестандартный синтаксис для этих матриц теперь будет просто псевдонимом для нового интерфейса DOMMatrix.

Так что иногда вынужденно стандартизированные нестандартные штуки со временем добираются до «нормальных» стандартов, и необходимость в «нестандартном стандарте» для них отпадает.

Но пока стандартные нестандартные штуки существуют — о них как минимум полезно знать. Чтобы применять их с умом и с пользой, без вреда для доступности и совместимости.

P.S. Это тоже может быть интересно: