Вендорные префиксы
Специальная запись CSS-свойств на этапе эксперимента.
Время чтения: 6 мин
Открыть/закрыть навигацию по статье
- Кратко
- Кто такие вендоры?
- Префиксы
- Где нужны префиксы?
- Директивы
- Псевдоклассы
- Значения свойств
- Селекторы
Обновлено 5 июля 2023
Кратко
Скопировать ссылку «Кратко» Скопировано
Вендорные префиксы — это приставки перед свойствами, селекторами, функциями или другими сущностями в CSS, позволяющие браузерам внедрять экспериментальные фичи до того, как они полностью стандартизированы и готовы для использования. Когда префикс отбрасывается — это знак, что всё готово.
Кто такие вендоры?
Скопировать ссылку «Кто такие вендоры?» Скопировано
Чтобы понять, что такое вендорные префиксы и зачем они нужны, надо немного разобраться с тем, как и кто разрабатывает CSS.
CSS — это одна из трёх основных мощных технологий, на которых строится веб. Его используют в своей работе тысячи разработчиков. А результат — стили сайта — видят миллионы пользователей.
Чтобы CSS во всём мире был единым, над его развитием работает так называемая Рабочая группа CSS (CSS Working Group), или коротко CSSWG. Они собирают потребности разработчиков сайтов и описывают возможности CSS в новых модулях. Получившийся документ называется спецификацией. В ней содержится описание того, как новое свойство должно работать.
Дальше наступает этап внедрения в браузеры. Каждый браузер разрабатывает отдельная компания, отдельные команды разработки. Когда в черновиках спецификации появляется новая CSS-фича, разработчики браузера начинают её реализовывать. Поскольку в спецификации не всегда описаны конкретные технические решения (черновик на то и черновик, что может меняться), то каждая команда разработки может делать это чуть иначе и принципы работы фичи вполне могут меняться со временем. До момента, пока не стабилизируется спецификация или пока не будут написаны все тесты, фича может работать в тестовом режиме, с вендорным префиксом.
Каждый браузер — это отдельный вендор (от англ. vendor — продавец) услуг просмотра сайтов, интернета. Отсюда и слово «вендорный». Буквально это означает, что существуют некие отдельные префиксы — они же приставки — которые работают в конкретном браузере — вендоре.
Префиксы
Скопировать ссылку «Префиксы» Скопировано
Основные браузеры используют следующие префиксы:
- -webkit — — Safari, Chrome, Opera 15+ и другие браузеры на основе движка WebKit или Blink.
- -moz — — Firefox и браузеры на движке Gecko.
- -o — — Opera 12 и раньше, на движке Presto.
- -ms — — Internet Explorer и старый Microsoft Edge 12–18.
Где нужны префиксы?
Скопировать ссылку «Где нужны префиксы?» Скопировано
В CSS существует много разных сущностей: селекторы и псевдоэлементы, свойства и их значения, функции, директивы. В процессе внедрения любой новой фичи используются вендорные префиксы.
Директивы
Скопировать ссылку «Директивы» Скопировано
Самый частый случай, когда вам может пригодится вендорный префикс для директивы — @keyframes :
@-webkit-keyframes animation 0% 100% > @keyframes animation 0% 100% >@-webkit-keyframes animation 0% left: 0; > 100% left: 100%; > > @keyframes animation 0% left: 0; > 100% left: 100%; > >Написать директивы @ — webkit — keyframes и @keyframes через запятую, чтобы не дублировать их содержимое, не получится.
Псевдоклассы
Скопировать ссылку «Псевдоклассы» Скопировано
В последнее время в CSS появляется много новых очень мощных псевдоклассов. Например, стилизовать плейсхолдер в поле ввода можно при помощи такого кода:
input::-webkit-input-placeholder color: #BADA55;> input:-moz-placeholder color: #BADA55;> input::-moz-placeholder color: #BADA55;> input:-ms-input-placeholder color: #BADA55;> input::-ms-input-placeholder color: #BADA55;> input::placeholder color: #BADA55;>input::-webkit-input-placeholder color: #BADA55; > input:-moz-placeholder color: #BADA55; > input::-moz-placeholder color: #BADA55; > input:-ms-input-placeholder color: #BADA55; > input::-ms-input-placeholder color: #BADA55; > input::placeholder color: #BADA55; >Как и в случае с директивами, префиксы в псевдоэлементах тоже приводят к дублированию кода: если перечислить всё через запятую, браузеры вас не поймут.
Значения свойств
Скопировать ссылку «Значения свойств» Скопировано
Бывает и так, что свойство старое, а вот значение для него новое, экспериментальное. В данный момент таким новым значением является функция image — set ( ) для свойства background — image :
div background-image: url('image.png'); background-image: -webkit-image-set(url('image.png') 1x, url('image-2x.png') 2x); background-image: image-set('image.png' 1x, 'image-2x.png' 2x);>div background-image: url('image.png'); background-image: -webkit-image-set(url('image.png') 1x, url('image-2x.png') 2x); background-image: image-set('image.png' 1x, 'image-2x.png' 2x); >Сначала браузер прочитает свойство background — image со значением url ( ) , которое он точно понимает. Потом увидит такое же свойство с другим значением, и если он его поймёт, то забудет первое свойство и применит второе. Это называется фолбэк.
Но браузер на этом не остановится и пойдёт дальше: если он поддерживает значение без префикса, то он предпочтёт его — ведь оно последнее. Поэтому порядок следования свойств с префиксами в значениях тоже важен: сначала идут значения с префиксами, потом — без, чтобы браузеры выбрали последний, максимально современный вариант.
Селекторы
Скопировать ссылку «Селекторы» Скопировано
Случается так, что в процессе внедрения фича меняется. Изначально планировалось, что функция выбора нескольких селекторов будет называться :any ( ) , потом :match ( ) , а в итоге пришли к :is ( ) . Чтобы селектор сработал везде, даже в старых браузерах, где функция называлась иначе, нужна будет такая запись:
:-moz-any(header, footer) a:hover color: red;> :-webkit-any(header, footer) a:hover color: red;> :matches(header, footer) a:hover color: red;> :is(header, footer) a:hover color: red;>:-moz-any(header, footer) a:hover color: red; > :-webkit-any(header, footer) a:hover color: red; > :matches(header, footer) a:hover color: red; > :is(header, footer) a:hover color: red; >В примере выше мы задаём красный цвет для ссылок при наведении курсора при условии, что эти ссылки находятся внутри или .
Как всё запомнить?
Скопировать ссылку «Как всё запомнить?» Скопировано
Скорее всего, вы сейчас думаете, а как же запомнить, где какие префиксы нужно писать, и для каких свойств они действительно нужны, а какие поддерживаются и без них.
Самый простой способ проверить поддержку свойства — найти его на сайте Can I use. Там, в том числе, написано, какие префиксы для каких браузеров нужны.
Но чаще всего разработчики не пишут префиксы руками, а используют инструменты автоматизации. Самым популярным из них на сегодня является Автопрефиксер. Вы можете попробовать его онлайн: вставляете ваш CSS, указываете, какие браузеры должны поддерживаться, и получаете код с проставленными префиксами там, где это нужно.
Порядок важен
Скопировать ссылку «Порядок важен» Скопировано
Очень важно указывать сущности (свойства, селекторы, директивы и так далее) с вендорными префиксами выше, чем без префиксов:
div -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;>div -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; >Это нужно для того, чтобы браузер использовал самую последнюю стабильную реализацию. Если браузер уже поддерживает фичу без префиксов, то применится последнее из перечисленных. А если нет, то сработает подходящая запись из кода выше.
Вендорные префиксы
На первый взгляд кажется, что вендорные префиксы это что-то из разряда грамматики. Вендорные префиксы, вендорные суффиксы и вендорные окончания. Но какое отношение это имеет к верстке?
Оказывается, самое прямое! Вендорные префиксы — это приставки к названию CSS свойства, которые добавляют производители браузеров для нестандартизированных свойств.
Согласно спецификации CSS 2.1 CSS идентификаторы, которые начинаются с «-» или «_» зарезервированы для CSS расширений браузеров. Наличие этих знаков в начале свойства гарантирует то, что в будущем расширения браузеров никогда не пересекутся со стандартными CSS свойствами. Т.е. ни один браузер не начнет «случайно» понимать свойство, которое для него не предназначено.
Какие они бывают?
Вендорные префиксы самых распространенных браузеров приведены в таблице ниже:
Вендорный префикс Производитель Браузер Браузерный движок -o-, -op-, -xv- Opera Software Opera Presto -moz- проект Mozilla Firefox, SeaMonkey, Camino и др. Gecko -ms- Microsoft Internet Explorer 8 Trident -khtml- проект KDE Safari до версии 3, Konqueror и др. KHTML послужил основой для WebKit -webkit- Apple Safari 3+, Google Chrome и др. WebKit Как это работает?
Для элемента прописывается CSS свойство в прямом виде для браузеров, которые его понимают. Следом за ним через точку с запятой перечисляется то же самое свойство, но с разными вендорными префиксами для разных браузеров. Браузер из такого кода интерпретирует только то свойства, которое написано под него, а написанные для других браузеров игнорирует.
Например, CSS свойство opacity, отвечающее за прозрачность элемента, кроссбраузерно используется так:
filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50); /* IE 5.5-7*/ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";/* IE 8*/ -moz-opacity:0.5;/* Mozilla 1.6 */ -khtml-opacity:0.5;/* Konqueror 3.1, Safari 1.1 */ opacity:0.5/* Safari 2.0+ , Chrome, Firefox Opera, */
Для чего это нужно?
В своем блоге разработчики Internet Explorer называют три причины использования вендорного префикса -ms- для браузера IE8:
- Если это свойство разработано только для Microsoft IE и не описано в спецификации или CSS модуле
- Если CSS модуль, к которому относится это свойство находится в разработке W3C и еще не достиг статуса кандидата в рекомендацию (Candidate Recommendation)
- Если свойство только частично реализует функции свойства, описанного в CSS модуле или спецификации
Остальные разработчики используют вендорные префиксы по схожим причинам. Например Mozilla имеет огромный перечень индивидуальных CSS свойств и их значений с вендорными префиксами -moz-, которые разработаны специально для Firefox, и не описаны ни в модуле CSS ни в спецификации.
Кроме того, разработчики Microsoft ухитрились с помощью вендорных префиксов скрывать от валидатора невалидные конструкции. Это касается, прежде всего, фильтров. Для IE 5.5-7 фильтр выглядел так:
filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50); /* IE 5.5-7*/
Такая конструкция пройти валидацию в принципе не может! Но ее преспокойно проходит новая конструкция того же фильтра, но уже для IE 8:
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";/* IE 8*/
Конечно, не очень хочется в коде писать несколько строчек кода с вендорными свойствами под каждый браузер вместо одной строчки кода со стандартными свойствами. Но не нужно забывать, что спецификация CSS3 пока еще находится в разработке. Возможно, что в описании свойства при стандартизации что-то поменяется, либо его совсем не будет в спецификации. Тогда безусловно разработчикам будет легче отказаться от вендорного свойства и поддерживать стандарты. Согласитесь, если в разных версиях браузера одно и то же свойство будет работать по-разному, ничего хорошего из этого не получится. Пускай лучше в старых версиях браузеров будут работать вендорные свойства, а новые версии будут поддерживать спецификацию в прямом виде, а свойства с вендорными префиксами будут игнорироваться.
Приятный бонус
Благодаря вендорным префиксам производители браузеров уже внедряют экспериментальные CSS3 свойства на свой страх и риск.
Верстальщик уже сейчас может реализовать большинство возможностей предоставляемых CSS3, в том числе разнообразные переходы и анимации без использования скриптов, но используя вендорные префиксы.
Наглядным примером такой реализации может быть использование CSS3 свойства transition. Поставим задачу реализовать для ссылки плавное изменение цвета фона при наведении курсора, не используя JavaScript. Для этого в CSS для ссылки нужно дописать следующий код
-webkit-transition:background-color 5s ease-in 3s;/* работает в Safari 3.1+, Chrome 1+ */ -o-transition:background-color 5s ease-in 3s;/* работает в Opera 10.5+ */ -moz-transition:background-color 5s ease-in 3s;/* планируется для Firefox 4.0+ */ transition:background-color 5s ease-in 3s;/* в прямом виде не поддерживает ни один браузер */
Живой пример можно посмотреть тут.
Кроме того, согласно заявлениям разработчиков, данный демо пример будет также работать в Firefox 4.0, первая бета версия которого вышла в июле года.
Подытожим
Вендорные префиксы — это специальные приставки к названию CSS свойства, заточенные под конкретный браузер, которые позволяют ему понимать экспериментальные CSS свойства и одновременно игнорировать записи, предназначенные для других браузеров.
Свойства с вендорными префиксами не соответствуют стандартам и не пройдут валидацию. Если тебя это не сильно беспокоит, их можно применять, т.к. в умелых руках это очень мощный инструмент. И многие ведущие студии рунета этим пользуются.
Заметка
Свойства по спецификации всегда пишем последними.
Материалы
- CSS 2.1 Specification:: Vendor-specific extensions
- MSDN:: Microsoft CSS Vendor Extensions
- developer.mozilla:: Mozilla CSS Extensions
- quirksmode:: CSS vendor prefixes considered harmful
- alistapart:: Prefix or Posthack by Eric Meyer
- Анатомия CSS
- История развития CSS
- Что такое CSS
- CSS анимация
- Анимация в CSS3. Часть I
- Анимация в CSS3. Часть II
- Вендорные префиксы
- Box model — блочная модель
- Схлопывание margin
- Блочные элементы
- Введение
- Дерево документа HTML
- Каскад в CSS
- Наследование
- Наследование: общие сведения
- Специфичность
- Вложенные таблицы стилей
- Внешние таблицы стилей
- Встроенные стили
- Группируем CSS. Директива @import
- Cелектор идентификатора
- Селектор атрибутов
- Селектор дочернего элемента
- Селектор класса
- Селектор обобщенных родственных элементов
- Селектор потомка
- Селектор сестринского элемента
- Селектор типа
- Селекторы псевдоклассов
- Селекторы псевдоэлементов
- Селекторы: общие сведения
- Составные селекторы. Комбинаторы
- Универсальный селектор
- Эффективность CSS селекторов
CSS — Префиксы браузеров
Веб-разработчик начинающий изучать теоретические основы CSS и использующий данные знания на практике может столкнуться с проблемами при рассмотрении реальных примеров. Это может вызвать у него непонимание происходящего и отбить дальнейшее желание изучать данную технологию.
Например, при рассмотрении стилей какого-нибудь сайта веб-разработчик может столкнуться со свойствами, содержащими впереди некоторые непонятные слова: -webkit- , -moz- , -ms- и др.
* { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; }Что же это такое? На самом деле всё просто, эти непонятные слова являются префиксами следующих браузеров:
- -webkit- : браузеры Chrome, Safari, Opera;
- -moz- : браузер Mozilla Firefox;
- -ms- : браузер Internet Explorer.
Таким образом, если перед названием свойства стоит некоторый префикс, то это означает, что данное свойство реализовано и будет применяться исключительно в указанном браузере. Все остальные браузеры данное свойство будут игнорировать, т.к. для них данный префикс неизвестен.
Причины появления префиксов
Причин для появления префиксов было достаточно много:
- Для включения в браузер экспериментальных свойств CSS, которые стандартом ещё не утверждены. Таким образом, производители браузеров производят тестирование и вносят предложения перед утверждением свойств CSS в стандарте.
- Для решения проблем с кроссбраузерностью.
- Для создания собственных свойств, которые не входят в стандарт CSS, но возможно появятся в нём через некоторое время.
Когда экспериментальное свойство утверждено в стандарте и прошло тестирование в браузере, у него обычно убирается префикс.
Как использовать префиксы
Рассмотрим в качестве примере следующий код:
* { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; }Данный код применяет свойства CSS, которые изменяют алгоритм расчёта ширины и высоты для всех элементов веб-страницы. Первое CSS свойство -webkit-box-sizing со значением border-box предназначено для браузеров, использующих движок webkit (Safari) или blink (Chrome, Opera, Яндекс.Браузер). Второе CSS свойство -moz-box-sizing со значением border-box предназначено для браузеров, использующих движок Gecko (Mozilla Firefox). Последнее CSS свойство предназначено для браузеров, в которых это свойство уже протестировано и внедрено в соответствии со стандартом.
При использовании префиксов для свойств CSS, необходимо помнить, что их следует располагать до свойства CSS без префикса. Почему это так важно? Это важно потому, что если когда-то в браузере будет реализовано оригинальное свойство (без префикса), то будет использоваться именно оно (т.к. оно располагается последним), а не его экспериментальная версия.
Например: применение свойства CSS ко всем элементам веб-страницы в браузере Google Chrome версии 40.

На рисунке выше видно, что оригинальное свойство box-sizing уже внедрено в этот браузер, и из-за того, что оно располагается последним, браузер использует именного его, а не вышеприведенное свойство -webkit-box-sizing .
Как проверить поддержку определенного свойства в браузере
Сайт, на котором можно проверить реализовано ли данное свойство или нет в конкретном браузере можно по ссылке приведённой ниже. Кроме этого на сайте показывается количество пользователей в процентах, которые пользуется этой версией браузера.
Например: проверим, как реализовано свойство transform в браузерах.

На сайте «CanIUse» браузеры отмечаются различными цветами, в зависимости от того в каком состоянии находится поддержка определённых свойств или тегов:
- Красный прямоугольник — браузер, в котором данное свойство не реализовано;
- Зелёный прямоугольник с дефисом, расположенным в правом верхнем углу – браузер, в котором данное свойство используется через префикс;
- Светло-зелёный прямоугольник – браузер, в котором данное свойство реализовано частично;
- Зелёный прямоугольник – браузер, в котором данное свойство реализовано в соответствии со стандартом.
Префиксы. Зачем и как правильно
Вадим Макеев: Добрый день! Я работаю в компании Opera Software, мы делаем разные браузеры. В своем докладе я буду не рекламировать какие-то крутые новинки, а расскажу о технологиях, которые мы используем повседневно. Поговорим о префиксах.
Префиксы используют все, но даже самые опытные специалисты порой не до конца понимают, как они работают. Для того, чтобы писать их правильно, нужно знать некоторые простые вещи, которые иногда оказываются совсем не простыми. Именно поэтому я расскажу вам о том, как это все работает.

Что может быть проще стула? Если в реальной жизни нам нужен стул, требуется одно простое действие – взять и поставить его. Но многие из вас пишут код, и вы периодически замечали, что некоторые свойства приходится повторять. Если у вас есть свойство «стул», вам нужно написать «-о-стул», чтобы все это нормально отобразилось в Opera. Потом вам понадобится «-ms-стул», «-moz-стул» и «-webkit-стул». Получается нагромождение, и совершенно непонятно, что с ним делать. И сесть на такой «стул» нельзя, и переносить неудобно.

Если вы каждый день сталкиваетесь с префиксами, то, честно говоря, они портят вам жизнь. 99 % людей мечтает, чтобы они исчезли и никогда не появлялись. Отчасти они правы, отчасти нет. Я объясню, почему.
Что собой представляют префиксы? Префикс, как правило, ставится перед значимым элементом и указывает на определенный браузер или производителя какой-либо техники. Префиксов существует очень много. Они могут начинаться как с дефиса, так и с нижнего подчеркивания. Префиксы – появились не в CSS 3, где они используются для таких вещей как градиент или “border-radius”, а еще в CSS 2.1. Это один из способов расширить CSS, добавляя туда собственные свойства, которые впоследствии можно стандартизировать.
На самом деле префиксы не «засоряют код». Изначально они были придуманы для того, чтобы помогать разработчикам браузеров адаптировать спецификацию под свои нужды и писать в них какие-то новые вещи. В итоги префиксы в большей степени стали использовать разработчики. Именно в этом кроется проблема.

Кстати, правильно называть префиксы именно «браузерными», а не «вендорными». В русском языке у слова «вендор» очень широкое значение. «Вендором», например, может быть и компания-поставщик холодильников. «Браузерный префикс» — это более удачный перевод.
Откуда вообще берутся префиксы? Давайте представим такую историю…
Где-то в Калифорнии, в Силиконовой долине утром просыпается разработчик webkit. Может быть, в офисе Google он заснул – бывает, трудоголики с работы не уходят. И во сне этому разработчику пришла идея свойства “lol-cat”. Он подумал, что классным значением для этого свойства будет вот такой милый смайлик.

«Надо бы внедрить это свойство», — решает разработчик. Но свойство нельзя внедрять в том виде, в котором оно ему приснилось. Сначала он должен спрятать его за пространством имен webkit.
Через некоторое время в Европе просыпаются разработчики из компании Mozilla. Они говорят: «Ага, ребята из Калифорнии придумали классное свойство “lol-cat”, давайте-ка мы тоже что-то придумаем. На самом деле, у нас в Европе принято другие смайлики рисовать. Поэтому нам нужно сделать другое значение!» И они вместо «домиков» делают «кругляшки». Кот у нас получается менее счастливым – может, он француз?

Но это неважно. Важно, что разработчики в Европе считают, что значение у свойства должно быть другим. Они очень вовремя добавляют префикс «-moz-», чтобы это свойство ни с чем не конфликтовало, чтобы только их браузер «понимал» это свойство и его значение. Браузер Mozilla префиксы «-moz-» «понимает».
Потом дело доходит до Норвегии, где нашего «кота» захотели сделать удивленным, и придумали свойству ещё одно значение.

Просто у каждого разработчика есть свое мнение относительно того, как все должно быть. Именно поэтому у нас был адский ад лет 10-15 назад – как раз из-за того, что разработчики не могли договориться друг с другом. Это нормальный процесс, это конкуренция. Есть масса людей, каждый из которых создает что-то, что, по его мнению, будет работать лучше. Для тех, кто живет в Калифорнии, лучше оказываются одни вещи, а для тех, кто живет в Европе, — другие.
Префиксы позволяют «прятать» все эти различия под браузерными пространствами имен и не мешать друг другу.
Но проходит полгода или год, проходит два года, три года, пять лет, и просыпаются разработчики из Консорциума всемирной паутины (W3C). Они говорят: «Никаких смайликов в значении не будет. У нас там будет стоять слово “smile”, потому что оно читаемо, понятно представителям всех культур и выглядит серьезно».

Эти разработчики пишут спецификацию, указывают типы смайликов, проверяют, чтобы совместимость этого свойства с другими была нормальной, все тестируют и выпускают спецификацию. Ее долго обсуждают, принимают версию «Кандидат в рекомендации». После этого W3C дает указание использовать беспрефиксную версию с тем значением, которое они утвердили. После прочтения новой спецификации владельцы всех браузеров должны избавиться от префиксов, убрать их из кода и использовать новое свойство. Но события развивались несколько по-другому. Об этом я еще расскажу.

Допустим, у нас есть свойство “box-shadow”. Когда совместимость была неполной, нам был нужен префикс. Мы писали вот так. Но это неправильно. Казалось бы, это естественно: пирамида должна стоять на самой широкой грани, чтобы быть устойчивой. Сначала идет “box-shadow”, потом “-moz- box-shadow”, затем “webkit-box-shadow”. Казалось бы, какая разница, в каком порядке свойства записывать, все равно каждое свойство адресуется каждому браузеру. Если ПО «понимает» свойство без префикса, оно «поймет» его без префикса, если оно «понимает» webkit, то оно «поймет» webkit. Но нет, все должно быть вот в таком порядке.

«Пирамида» должна «висеть» острием вниз. Необязательно, чтобы сначала шла часть с “webkit-…”, а потом часть с “-moz-”, их можно поменять местами. Главное, чтобы свойство “box-shadow” шло последним. Организация ровной «пирамиды» просто помогает визуально определить, все ли у вас в порядке с префиксами.
Зачем это вообще нужно? Представьте, что производители браузеров не успели отказаться от префиксов. Допустим, webkit-браузеры практически не отбрасывают префиксы, у них такая политика. То есть они сознательно не поступают так, как им рекомендует W3C. Думаю, они не делают этого потому, что есть старые версии iTunes, которые частично используют webkit, и надо, чтобы они справлялись с рендерингом страниц.
В итоге браузер, который сделал нормальную реализацию свойства, применит “smile”. А если это Mozilla Firefox, он дойдет до свойства с префиксом “-moz-”, то он может после правильного “smile” применить старое значение – возникнет ошибка. Если в браузере реализовано 2 типа свойств (с префиксом и без него), то будут применены те свойство и значение, которые расположены последними. Поэтому в конце должно стоять новое свойство без префикса.

Это главное правило, которое нужно знать при использовании префиксов. Многие этого не понимают. Свойство без префикса идет последним.
Кто-то может задать вопрос: иначе что? Я покажу, что произойдет в этом случае. Допустим, у элемента есть свойство “webkit-box-shadow”, размер тени 400 пикселей, отступ от центра 200 пикселей, тень черного цвета. Есть свойство “box-shadow” с теми же самыми значениями, они абсолютно одинаковы. Вот в таком порядке мы их записали – сначала с префиксом, потом без.

Текущий Chrome или Safari рендерят это вот так.

У нас есть блок нулевых размеров, к которому применена такая тень. Если мы поменяем порядок свойств (сначала свойство без префикса, а потом свойство с префиксом), то у нас получится вот что.

Рендеринг тени зависит от порядка свойств, потому что под версией без префикса «спрятана» более качественная и совместимая реализация. Возможно, она даже быстрее работает. Но главная ее ценность в том, что она совместима с другими браузерами.
То есть во всех браузерах будет вот такая хорошая тень.
А в браузере, для которого вы запишете префиксы в неправильном порядке, будет то нечто, которое я показывал.
Поэтому, чтобы применить самые новые и последние спецификации, пишите свойство без префиксов последним. Все свойства с префиксами нужны для поддержки старых браузеров на Android 2.1, например.
Что можно порекомендовать при работе с префиксами? У нас есть множество свойств для разных старых браузеров. Если вы делаете градиенты, применяете “transform”, “transition origin”, кода становится очень много. Есть варианты того, как этого можно избежать.

Самый интересный вариант из тех, что мне попадались за последнее время, это Prefix Free. Лия Веру, которая тоже выступала здесь на конференции РИТ++, написала JavaScript-библиотеку, которая находит свойства без префиксов и добавляет к ним префиксные свойства, притом не все, а только необходимые.
В самой библиотеке нет списка префиксов. JavaScript проверяет, какие префиксы «поймет» браузер, и добавляет только их. Это классное изобретение. Потому что в большинстве своем препроцессоры просто берут и добавляют все, что можно. А эта библиотека динамическая и добавляет только то, что нужно. Поэтому код у нас не «распухает». Количество правил в блоке, пусть даже невалидных правил, может влиять на производительность.
У этой библиотеки есть некоторые недостатки. Со сложным CSS вроде импорта она не работает, потому что внутрь не забирается. По-моему, это тоже можно решить, но это сильно усложнит код. Еще один недостаток состоит в том, что библиотека нагружает отрисовку.
Допустим, если вы делаете какой-то JS-fiddle, чтобы быстро посмотреть, как работает ваш код, такая библиотека будет идеальным вариантом. Лия Веру даже создала свой сервис для просмотра демонстраций – Tablet.Com. Там используется эта библиотека. Если вы напишите там градиент без префиксов, он заработает во всех браузерах, потому что библиотека автоматически его подставит.
Это быстрое JavaScript-решение. Для серьезных вещей оно не годится. Для них используются препроцессоры. Связка Sass и Compass работает на Ruby, они просто запускаются на локальной машине и обрабатывают ваши файлы. Less и Stylus могут работать как в качестве запущенных скриптов с чтением из файлов, так и при подключении в браузере. Это позволяет легко выполнять отладку без необходимости каждый раз переписывать файлы заново. Но у них есть некоторые особенности.

Препроцессоры популярны, потому что всем нам нравится, когда кода мало. Тем не менее, у них есть одна главная проблема – это их «глупость». Я сейчас расскажу о каждом из них.

Начнем с Compass. Compass позволяет писать свойства в двух нотациях. Через «собаку» — @include border-radius, также можно писать свойство через знак «плюс», что заодно поможет отказаться от фигурных скобок. В обоих случаях мы получим добавление префиксов для данного свойства. Это позволит получить и “-webkit-border-radius”, и “-moz-border-radius”, и так далее. Значение вы указываете тут же.

Какие провалы есть у Compass? Когда Compass добавляет префиксы, у нас появляются 2 свойства, которых не существует в природе. Их никогда не было и никогда не будет. Свойства “-o-border-radius” и “-ms-border-radius” не нужны в принципе. У нас есть избыточность в виде 2 лишних строк кода. Создатели не потратили лишних полчаса, чтобы изучить, какие свойства действительно нужно разворачивать. Modernizer, кстати, отказался от свойств khtml, потому что браузера под Linux, из идеи которого «родился» webkit, не существует. Разработчики khtml сами сказали, что будут использовать последний webkit для своего браузера Conqueror. Таким образом, три свойства с префиксами, которые предлагает Compass, лишние.

Какие еще провалы Compass стоит упомянуть? Забыт префикс “-ms-“ для свойств “transform” и “transition. У свойства “box-shadow” масса ненужных префиксов. Есть ненужный префикс “-o-“ для свойства “column”, которое делает несколько колонок. Для свойства “background-size” тоже есть ненужный префикс “-o-“, мы его поддерживаем без префикса. Если вы используете в коде “opacity”, Compass автоматически понапишет там “filter:progid:DXImage…”, причем он использует старую и невалидную версию, без “-ms-filter-…”, без кавычек и так далее. Ваш код будет испорчен.
Кстати, на поиск всех этих ошибок у меня ушло не более 15 минут. Не знаю, сколько времени нужно, чтобы их поправить. Минут 10, наверное. Несмотря на все ошибки, это по-прежнему одна из самых популярных библиотек для работы с префиксами.

Теперь поговорим о библиотеке Less. Она позволяет писать свойства через точку. И либо в коде, либо в каких-то отдельно подключаемых вещах у вас будет записываться, что происходит, какие значения он принимает. И вот он разворачивается в такие строки с префиксами. Казалось бы, все нормально. Но на сайте, в официальной документации использован неправильный порядок свойств. Те, кто делает библиотеку для работы с префиксами, не знают, как работает префикс.

Еще один пример с Less. Там все правильно, там нет лишних префиксов, насколько я понял, но порядок свойств они выводят неправильный по умолчанию. Вы можете написать собственные сниппеты, но правильный порядок не предполагается по умолчанию, у всех. А людей, которые пишут собственные сниппеты, единицы.

Stylus – это, на мой взгляд, самый гибкий из существующих препроцессоров. Это одна из самых адекватных библиотек для работы с префиксами, потому что она позволяет писать код очень гибко. Можно использовать массу нотаций, убирать фигурные скобки, точки с запятой, объявлять переменные без всяких префиксов. В моем примере “fonts” – это переменная, не нужно значка доллара, подчеркиваний или еще чего-то. Просто пишете «равно» и можете эту переменную дальше использовать.

Stylus – самый «молодой» препроцессор. В нем есть проблемы. Например, если вы поставите такие скобки, все поломается. Я «отбиваю» последнюю скобку, мне удобнее читать код, когда скобка «отбита». А здесь получается так: «отбил» скобку – сломал целый файл. Это несерьезно, хотя в остальном библиотека хорошая. Всем, кто делает такие библиотеки, советую писать пул запросов.
Префиксы можно использовать не только в CSS, но и в JavaScript. Если у вас есть какая-то анимация, например.
Как мы привыкли работать со свойствами в JavaScript? Если свойство состоит из двух слов, разделенных дефисом, мы берем и убираем дефис, а следующую букву делаем заглавной. Это называется «верблюдизацией» (Lower Camel Case), то есть первая буква строчная, а все остальные буквы заглавные. Это много где описано, мы привыкли работать с этим.

То же самое должно происходить с префиксами. Мы берем и заменяем префикс на букву. А поскольку это первая буква, то она будет строчной, а остальные заглавными. Получится примерно так.

По идее, все просто. Надо написать несколько строк кода, чтобы свойства заработали во всех браузерах. Допустим, нам нужно задать Transition Timing Function.

На первый взгляд, все нормально. Тестируем в браузере… Строки для префиксов “-moz-“ и “-o-“ не работают. Само свойство браузер поддерживает, но строки не работают.

Попробуем сделать первые буквы заглавными.

Тогда перестает работать строка, начинающаяся с “Ms” для IE.
Читаем спецификацию. Дословно там прописано, что с префиксами следует поступать так: дефис и буква превращаются в заглавную букву. Это должно применяться везде. По спецификации, первая буква должна быть заглавной.

А по факту в браузерах есть различия. Mozilla и Opera буквально следуют спецификации, Firefox и Opera «понимают» префиксы только тогда, когда первая буква прописная. Internet Explorer «понимаeт» их только тогда, когда первая буква строчная. Webkit «понимаeт» оба варианта.

Тем не менее, написанная только прописными буквами строка GETELEMENTBYID в JavaScript не сработает. Появляются какие-то двойные стандарты: в одном месте есть гибкость, в другом ее нет. Почему бы не сделать JavaScript независимым от регистра?
На самом деле, всем производителям браузерам стоит внимательнее читать спецификацию. Периодически к нам обращаются разработчики, которые жалуются, что у них что-то не работает. Мы им отвечаем, что все реализовано в строгом соответствии со спецификацией, а не с ориентацией на другие браузеры. Такое периодически случается. Разработчикам мои разъяснения не помогают, естественно. Я себя чувствую виноватым из-за того, что мы сделали что-то не так, как в других браузерах.
Грядет страшное!
А сейчас я вынужден предупредить вас о том, что скоро все будет очень плохо. Opera, Mozilla и Microsoft собираются поддерживать свойства с префиксом “-webkit-”. Компания Mozilla заявила об этом. Они в этом заинтересованы, потому что им кажется, что их игнорируют разработчики, пишущие для iPhone. Opera и Microsoft тоже заинтересовались поддержкой этого префикса. На мероприятии CSS Working Group это обсуждалось. Возможно, я сейчас выдаю инсайдерскую информацию, но этот вопрос уже решен. Это случится очень скоро.
Безусловно, когда мы начнем поддерживать свойства с префиксом “-webkit-”, мы выпустим тестовую сборку, чтобы все могли проверить, что «отвалится» у них на сайтах, что начнет работать лучше, и так далее.

На самом деле, это не просто какая-то вольность. Было проведено специальное исследование. Аналитики компании Alexa взяли Топ 100 сайтов по всему миру и посчитали, какие свойства там используются. Свойств “-webkit-box-shadow” оказалось почти 800 штук. Свойств “-moz-border-radius” чуть меньше, “- webkit-border-radius» практически столько же. Дальше уже разрыв гораздо больше. Тут нет ни свойств Opera, почти нет свойств Microsoft Internet Explorer.

На диаграмме в процентном содержании показано распределение свойств, которые в целом используют разработчики. То есть про “-moz-» помнят, про “-webkit-” помнят, а про “-o-» и “-ms-» практически никогда не помнят, даже если браузер поддерживает эти свойства.
Поэтому нужно что-то делать. У нас в компании есть целый отдел Open Relations, там идет работа над проектом “Open the Web», где люди занимаются тем, что пишут разработчикам: «Пожалуйста, не блокируйте Opera! Мы поддерживаем это свойство. Напишите строчку кода!» А разработчики нам отвечают: «Да? А мы думали, что Opera – это мобильный браузер… Окей!» Иногда они не соглашаются, ссылаясь на малую распространенность Opera. Да, наш браузер по-разному распространен в разных регионах мира, но это не повод не давать ему то, что он может «понять»!
Поэтому и мы, и компания Mozilla (которую упоминают часто), решили заняться этим сомнительным делом с поддержкой свойств “-webkit-”. Возможно, от этого многое поломается, но многое и исправится.
Мы уже делали так раньше. Посмотрите любой User Agent браузера – что там написано? Там написано “like Mozilla”, то есть все идентично. Это способ сделать User Agent совместимым с сайтами, которые его проверяют и так далее. Сейчас User Agent каждого браузера представляет собой «кашу». Там множество строк, которые отвечают только за то, чтобы старые сайты не сломались. Долгое время браузеры поддерживали “document.all”, некоторые до сих пор его поддерживают. Если вы протестируете поддержку “document.all”, мы скажем, что ее нет, а если мы ей воспользуемся, окажется, что она будет. Для обратной совместимости.
Будут поддерживаться не все свойства “-webkit-”, а только избранные и нужные. Если мы пока не поддерживаем 3D-трансформацию (над этим наши специалисты пока работают), мы не будем делать вид, что мы ее поддерживаем. Будут поддерживаться только те свойства, которые «понимает» наш браузер, те, которые улучшат совместимость.
Если сейчас через Opera Mobile зайти на сайт, сделанный для iPhone, окажется, что у нас белый текст на белом фоне.

Если автоматически добавить нужные префиксы каким-то простым скриптом, все будет работать хорошо, — будет черный текст на синем фоне, например.

Мы пытаемся улучшить то, что видит пользователь, мы не пытаемся испортить жизнь разработчикам. Я сам разработчик, я сам был не в восторге от этой идеи поначалу. Постепенно привыкаю к этой мысли.

Свойства “-webkit-” будут применяться только в случае отсутствия свойств для Opera. Если будут найдены свойства для Opera, они будут применяться прежде всего. Каскады будут сохраняться, сайты для iPhone заработают.
Я предчувствую, что что-нибудь обязательно сломается. Поэтому мы при начале поддержки свойств “-webkit-” постараемся сообщить об этом всем. Нужно, чтобы все успели протестировать свои сайты.
Может случиться еще кое-что другое. Недавно я говорил с человеком из CSS Working Group, который занимается в том числе и спецификациями, он мой коллега. Он рассказал, что в CSS Working Group есть и другая идея относительно работы с префиксами. Объясню на примере.

Браузер «икс» внедрил свойство “lol-cat:smile” без префикса, но в какой-то момент обнаружилась ошибка. Чтобы исправить эту ошибку, он внедрит исправленную версию этого свойства с префиксом. Тогда разработчики смогут исправить ошибку, использовав префикс.

Как видно из примера, порядок свойств здесь другой. Текущий подход предполагает использование «пирамиды» острием вниз, а подход, который, возможно, предложит CSS Working Group, предлагает другую «пирамиду» — острием вверх. Так что неизвестно, что будет считаться правильным в перспективе. Пока правильно то, о чем я говорил в начале доклада. Что будет через год, два или три, мы не знаем. Префиксы не дадут нам заскучать. Помните главное: свойство без префикса идет последним.
Приведу ссылки на статьи, в которых есть более подробная информация о работе с префиксами. Первая статья Эрика Мейера дана в переводе. В остальных ведется дискуссия о префиксах, которая длится уже полгода. Люди буквально сражаются за то, чтобы или убрать префиксы совсем, или, наконец, сделать их удобными.

Большое вам спасибо за внимание. Жду вопросов.
Вопросы и ответы
Реплика из зала: Привет. Хочу сделать комментарий. Начну с того, что “khtml” был давно убран из Compass , а “transform” был исправлен. Opacity с префиксами не работает уже, их не нужно добавлять.
Вадим Макеев: Там с opacity проблема в том, что добавляется невалидный CSS-код.
Реплика из зала: Этот невалидный CSS-код нужен, чтобы поддерживался старый IE.
Вадим Макеев: Все, понял.
Вопрос из зала: Вопрос про другое. Есть ли какие-нибудь идеи (может быть, ты их знаешь), почему-то их не внедряют… Почему бы не сделать общий префикс для всех браузеров, например, “-beta-“ и оставить префиксы для всех браузеров на случай, если какие-то браузеры реализуют это свойство неправильно?
Вадим Макеев: Тогда тебе в коде придется писать не 6, а 7 строк.
Реплика из зала: Но большинство свойств реализовано всеми браузерами одинаково.
Вадим Макеев: Понимаешь, если у тебя какой-то крупный проект, и тебе важна полная совместимость, ты будешь писать все свойства… То есть ты предлагаешь эту ситуацию еще больше ухудшить…
Реплика из зала: Но потом-то будет лучше, когда «умрут» старые браузеры, которые не поддерживали общий префикс…
Вадим Макеев: На самом деле, таких дискуссий очень много. Главная идея, с которой согласны все: префиксы в текущем состоянии всех «достали». С этим нужно что-то делать. Есть еще потрясающий аргумент: префиксы – это экспериментальные свойства. У вас стабильный проект, зачем ему экспериментальные свойства? Мы вежливо улыбаемся ребятам из W3C и говорим: «Конечно, вы молодцы, что пишете спецификации, но сайты вы хоть раз разрабатывали?» Дискуссий много. Я рассказал о том, что есть. О том, что будет, я не могу рассказать. Я не гадалка.
Реплика из зала: Я, например, стараюсь писать префиксы вручную и быть в курсе, что сейчас где используется…
Вадим Макеев: Таких, как ты, мало.
Вопрос из зала: Штука в том, что помнить об этом и следить за изменениями не всегда просто и не всегда нужно. На самом деле, нас еще в университете учили, что не нужно ничего запоминать. Нужно думать и искать информацию. Сейчас для того, чтобы найти список актуальных префиксов, нужно перебрать примерно пять статей, хорошенько «полазить» по сайтам производителей… Не было ли когда-нибудь мысли создать сводный проект по префиксам, где можно будет посмотреть, в каких версиях движков что работает или не работает? Просто хочется знать, что поддерживается…
Вадим Макеев: Нужно «перелопатить» огромное количество данных. В последнее время на Западе очень популярны проекты типа «Все свойства такого-то браузера», «Все префиксы такого-то браузера», поддержка CSS 3, HTML 5, и так далее. Сейчас много таких проектов. Не удивлюсь, если в какой-то момент появится и то, о чем вы говорите. Есть парочка страниц, на которых собираются все свойства с префиксами всех известных браузеров. Две из них я знаю. Ссылок на них я не давал, но их можно найти довольно легко. Сводного проекта нет, но я бы с удовольствием поучаствовал в его создании.
Реплика из зала: Я бы тоже хотел поучаствовать в его создании. Есть основной момент… Собирать эти свойства с каких-то посторонних страниц крайне неприятно. Скажи, насколько возможно общение непосредственно с производителями браузеров, привлечение их к участию в таком проекте? Или хотя бы «вытягивать» данные из конкретных мест, где они будут их размещать.
Вадим Макеев: Я так понимаю, что ты бы хотел, чтобы сами производители браузеров выкладывали какой-нибудь файл XML или JSON со всеми префиксами? Это будет слишком накладно, мы же все очень занятые люди. Но я знаю, кого дернуть за рукав, чтобы получить актуальные списки – в принципе, это реально. Но вот обновлять их все-таки придется вручную.
Вопрос из зала: Что ты имеешь в виду? Придется каждый раз запрашивать у специалиста список, или в каком-то виде на каком-то ресурсе этот список будет фигурировать?
Вадим Макеев: Допустим, у нас есть страница, на которой есть все свойства с префиксами.
Реплика из зала: Вы практически святые в этом плане. Не стоит обобщать.
Вадим Макеев: Документация хорошая, мне правда нравится. Да, иногда мы добавляем туда свойства с опозданием на неделю, на месяц. У нас сильно загружен человек, который занимается документацией.
Реплика из зала: Ок.
Реплика из зала: Кстати, насчет гордости за документацию: мои переводы вы так и не опубликовали!
Вадим Макеев: Мы с вами свяжемся!
Реплика из зала: По поводу единого сайта, где указаны все префиксы… На сайте Mozilla Developer Center всегда указаны префиксы и версии, в которых все это работает. Единственное исключение – там практически не показана информация для каких-то технологий, которые не работают в Mozilla, но их достаточно мало.
Вадим Макеев: На самом деле, самый простой способ найти префиксы прямо сейчас – это зайти на сайт webstandards.ru и ввести в строке поиска слово «префиксы». Примерно полгода или год назад мы писали новость со ссылками на страницы, где описаны все браузерные префиксы. Еще вопросы?
Вопрос из зала: Когда Opera начнет префиксы webkit, она будет поддерживать их так, как это у вас уже реализовано, или так, как это реализовано в webkit?
Вадим Макеев: Нет, мы просто будем «мапить» существующие свойства на свойства webkit. Есть еще один момент… Мы сейчас работаем над новой спецификацией Flexbox, она уже настолько финализирована, что ее можно внедрять. За последние полгода ее переписали практически с нуля. Там есть общие слова, но суть там очень сильно поменялась. Когда мы внедрим новую спецификацию Flexbox, мы посмотрим сайты и, возможно, сделаем совместимость со старой. Мы не просто будем реализовывать спецификацию, а «замапим» нужные свойства в виде ссылки.
Допустим, вы пишете какой-нибудь webkit Flexbox или просто Flexbox в старой нотации, а он раз – и начинает работать по спецификации. Мы не будем писать вторую реализацию, не будем «форкать».
Реплика из зала: У меня не вопрос, а небольшое предостережение. Вы компетентный специалист, и в вашем докладе прозвучали нотки антиагитации против использования Less и других подобных инструментов, правильно? Было такое, пусть и в неявном виде. А инструмент хороший, просто в нем есть некоторые нюансы, которые вы перечислили. Но сам инструмент очень облегчает жизнь. Я смотрел в исходники Less. На первых порах было много проблем с парсингом CSS, были какие-то ошибки, нельзя было вставить комментарии внутрь значения CSS-свойства. Все «валилось», да и сейчас так, по-моему. Вся проблема Less в том, что они разбирают CSS регулярными выражениями. Наверное, остальные препроцессоры работают сходным образом. А это, по-моему, абсолютно неправильно. У CSS слишком сложная структура для того, чтобы разбирать его на регулярные выражения.
Вадим Макеев: У молодого человека, который с микрофоном ходит, есть проект CSScomb, который разбирает CSS не регулярными выражениями, а построчно. Не просто пытается понять, как CSS работает, но разбирает его на какие-то простые структуры.
Реплика из зала: На простые структуры можно разбить CSS, описав CSS в виде БНФ, то есть формы Бэкуса-Наура. В Mozilla Developer Network все спецификации в виде псевдо-БНФ… Если так описать, то будет очень гибкий инструмент для анализа и трансформации CSS.
Вадим Макеев: Если там написано выражение (англ. expression), в которое вставляется таблица… Да?
Реплика из зала: Как раз SCSS под проекты SASS (оперативный синтаксис, совместимый с CSS) не использует регулярные выражения, он честно все парсит, и когда он вышел, было заявлено, что его парсер справится с любым валидным CSS-документом, включая невалидные расширения для IE.
Вадим Макеев: То есть если там «закавычена» таблица на 300 строк, он не сломается?
Реплика из зала: Если это нормально обрабатывается в браузерах, то проблем не будет.
Вопрос из зала: У меня вопрос: почему вы не перейдете на движок webkit?
Вадим Макеев: Тема слишком обширна. Попробую ответить кратко. Потому, что это не имеет смысла вообще. Нам придется уволить всех наших инженеров. Впрочем, есть более важный аспект. Я не с того пункта начал. Проект webkit контролируется компаниями Apple и Google. Чтобы получить право отправлять обновления (англ. commit) в основное ядро проекта, нужно иметь проверяющих (англ. reviewer) где-нибудь в Калифорнии, платить им как вице-президентам нефтяных компаний. Также стоит иметь в виду, что 90 % проверяющих ядра webkit связаны с Apple и Google. Все, что им не понравится, они будут отклонять. Чтобы начать разрабатывать движок, нельзя просто «форкнуть» Google и начать его писать. Это кажется классным и интересным. Но это повлечет за собой огромное количество проблем. Мы обсуждали эту возможность, это адекватно. Мы не хотим поддерживать что-то свое, но плохое. Мы хотим, чтобы пользователям было удобно. Но для того, чтобы им было удобно, мы должны иметь возможность гибко разрабатывать то, что мы хотим. Переход на webkit нам этой гибкости не даст. Мы просто разоримся.
Реплика из зала: У меня не вопрос, а замечание по поводу дискуссии о webkit и так далее. Я ещё помню времена, когда очень распространенным браузером был IE5. Монополия движка какого-то одного браузера ни к чему хорошему не приводит. Сейчас прекрасное время. Конкуренция дает массу преимуществ. Мы сейчас ими пользуемся, и будем пользоваться еще достаточно долго. Хорошо, что у нас есть разные браузеры. Здорово, что они продолжают появляться и что они делают друг друга лучше.