От автора: в этой статье я подробно рассмотрю правило @supports и связанное с ним JavaScript API.
Для решения проблемы поддержки новейших технологий в браузерах используются два основных метода: метод грациозной деградации и прогрессивного улучшения. Метод грациозной деградации позволяет пользователям, использующим современные браузеры, ощутить весь функционал передовых технологий. А тем, кто использует старые версии браузера, будет предоставлена версия сайта с ограниченным функционалом.
С техникой прогрессивного улучшения разработчики устанавливают базовую линию для дизайна, тот уровень пользовательского опыта, который поддерживает большинство браузеров. В таких веб-приложениях есть встроенная функция определения браузера. Данную функцию они могут использовать для увеличения функционала сайта по мере возможностей браузера, а значит, и для улучшения пользовательского опыта. Самый распространенный инструмент в технике прогрессивного улучшения это JS библиотека Modernizr.
Modernizr программно проверяет, поддерживает ли браузер веб-технологии следующего поколения, и соответственно возвращает true или false. Вооружившись этим знанием, вы можете использовать новые свойства в поддерживающих их браузерах, а для старых браузеров использовать надежные, проверенные методы.

Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
Узнать подробнееЗвучит хорошо, но вот уже некоторое время на слуху метод куда лучше. Функцию определения можно реализовать при помощи CSS запросов через правило @supports.
Функция определения браузера через @supports
Правило @supports является частью CSS3 спецификации по условным правилам, которая также включает в себя более широкое правило @media, которым все мы пользуемся при создании адаптивного дизайна. Медиа запросы позволяют обнаружить такие свойства как ширина и высота области окна браузера, в то время как @supports позволяет проверить поддержку браузером пары CSS свойство/значение.
Рассмотрим простой пример. Скажем, на веб-странице есть изображение, к которому вы хотите применить режимы наложения. Режимы наложения не поддерживаются в старых браузерах. Однако вместо того, чтобы показывать пользователям, чей браузер не поддерживает данную функцию, изображение по умолчанию, можно, если не полностью копировать эффект, то хотя бы показывать что-то похожее. Ниже показано, как проверить поддержку режимов наложения через @supports:
1 2 3 4 5 6 7 |
@supports (mix-blend-mode: overlay) { .example { mix-blend-mode: overlay; } } |
Чтобы добавить стили в браузеры без поддержки mix-blend-mode, необходимо использовать синтаксис:
1 2 3 4 5 6 7 |
@supports not(mix-blend-mode: overlay) { .example { /* альтернативные стили */ } } |
Несколько замечаний:
Условие должно быть внутри скобок. Т.е. запись @supports mix-blend-mode: overlay { … } неверна. Тем не менее, если добавить лишние пары скобок, все будет работать нормально. К примеру, запись @supports ((mix-blend-mode: overlay)) верна.
В условии должно быть как само свойство, так и его значение. В примере выше мы проверяем свойство mix-blend-mode на значение overlay.
Добавление в конце конструкции !important не влияет на правильность кода.
Давайте сделаем по примеру выше небольшое демо. Браузеры с поддержкой mix-blend-mode будут применять стили из блока @supports() { … }; остальные браузеры будут брать стили из блока @supports not() { … }.
1 2 3 |
<article class="artwork"> <img src="myimg.jpg" alt="cityscape"> </article> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@supports (mix-blend-mode: overlay) { .artwork img { mix-blend-mode: overlay; } } @supports not(mix-blend-mode: overlay) { .artwork img { opacity: 0.5; } } |
Демо на CodePen:
Тест нескольких условий зараз
В тестах свойств через @supports нам не ограничивают количество условий, которые можно составить в одной конструкции. Поставить несколько условий можно при помощи логических операторов and, or, и вышеупомянутого not. Оператор конъюнкции and проверяет соблюдение нескольких условий:
1 2 3 4 5 6 |
@supports (property1: value1) and (property2: value2) { element { property1: value1; property2: value2; } } |
С помощью оператора дизъюнкции or набор стилей можно задать различным свойствам. Очень удобно, если некоторым свойствам или значениям нужно прописать вендорные префиксы:
1 2 3 4 5 6 |
@supports (property1: value1) or (-webkit-property1: value1) { element { -webkit-property1: value1; property1: value1; } } |
В одном @supports правиле можно комбинировать операторы and и or:
1 2 3 4 5 6 7 8 9 |
@supports ((property1: value1) or (-webkit-property1: value1)) and (property2: value2) { element { -webkit-property1: value1; property1: value1; property2: value2; } } |
Ключевое значение при группировке условий играют скобки. Просто расставить операторы and, or или not не получится. Также способ группировки условий в скобках определит порядок, в котором будут читаться данные условия. В коде выше дизъюнкция or читается первой, затем результат условия сравнивается со следующим условием and.
При помощи слова not можно проверить одно условие зараз. К примеру, код ниже неверен:
1 2 3 |
@supports not (property1: value1) and (property2: value2) { /* стили... */ } |
Вместо этого необходимо сгруппировать все условия под одно ключевое слово not при помощи скобок. Ниже правильная запись кода:

Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
Узнать подробнее
1 2 3 |
@supports not ((property1: value1) and (property2: value2)) { /* стили... */ } |
Осталось убедиться, что после not стоит пробел, а также с обеих сторон от and и or.
Операторы в действии
Если браузер поддерживает градиенты и режимы наложения, то к нему можно применить набор стилей, как показано ниже (я разбил код ниже на несколько строк для лучшей читаемости):
1 2 3 4 5 6 7 8 9 10 11 12 |
@supports (mix-blend-mode: overlay) and (background: linear-gradient(rgb(12, 185, 242), rgb(6, 49, 64))) { .artwork { background: linear-gradient(rgb(12, 185, 242), rgb(6, 49, 64)); } .artwork img { mix-blend-mode: overlay; } } |
Так как некоторым старым Android браузерам необходим префикс -webkit- для линейных градиентов, давайте встроим дополнительное условие в блок @supports:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@supports (mix-blend-mode: luminosity) and ( (background: linear-gradient(rgb(12, 185, 242), rgb(6, 49, 64))) or (background: -webkit-linear-gradient(rgb(12, 185, 242), rgb(6, 49, 64))) ) { .artwork { background: -webkit-linear-gradient(rgb(12, 185, 242), rgb(6, 49, 64)); background: linear-gradient(rgb(12, 185, 242), rgb(6, 49, 64)); } .artwork img { mix-blend-mode: luminosity; } } |
К примеру, на вашем сайте стоят значения режимов наложения luminosity и saturation, которые на момент написания статьи не поддерживаются в браузере Safari. Но вы хотите добавить альтернативные стили для этих браузеров. В таком случае нам поможет @supports not и and:
1 2 3 4 5 6 7 8 9 10 11 |
@supports not ( (mix-blend-mode: luminosity) and (mix-blend-mode: saturation) ) { .artwork img { mix-blend-mode: overlay; } } |
Все демо можно найти на CodePen:
JavaScript и CSS запросы
Воспользоваться всеми преимуществами CSS запросов можно при помощи JavaScript CSS интерфейса и функции supports(). Функцию Css.supports() можно написать двумя способами. Первый и наиболее поддерживаемый синтаксис принимает два аргумента: свойство и его значение, а возвращает true или false:
1 |
CSS.supports('mix-blend-mode', 'overlay') |
Не забудьте написать свойство и его значение в кавычках. Спецификация ясно говорит, что функция возвращает true, если выполняются два условия:
Имя переданного свойства «буквально совпадает с именем CSS свойства», которое должен поддерживать браузер;
Значение будет «проверено, если это значение поддерживается свойством».
Под буквальным совпадением спецификация понимает, что символы перехода на новую строку не обрабатываются и пробелы не удаляются. Поэтому не ставьте лишних пробелов в конце или начале слова, иначе вернется false. Альтернативный синтаксис принимает только один аргумент в скобках:
1 |
CSS.supports('(mix-blend-mode: overlay)') |
Данный синтаксис удобнее для проверки нескольких условий при помощи and и or. Ниже маленький пример. Скажем, вы хотите проверить, поддерживает ли браузер режим наложения luminosity. Если да, то JS динамически добавит класс luminosity-blend к соответствующему элементу. В противном случае будет добавлен класс noluminosity. Соответственно к элементу применятся нужные стили.
1 2 3 4 5 6 7 |
.luminosity-blend { mix-blend-mode: luminosity; } .noluminosity { mix-blend-mode: overlay; } |
Если использовать первый синтаксис, то JS код будет следующий:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var init = function() { var test = CSS.supports('mix-blend-mode', 'luminosity'), targetElement = document.querySelector('img'); if (test) { targetElement.classList.add('luminosity-blend'); } else { targetElement.classList.add('noluminosity'); } }; window.addEventListener('DOMContentLoaded', init, false); |
Если вам нравится новый синтаксис с одной переменной, просто замените соответствующую строку кода на строку ниже:
1 |
var test = CSS.supports('(mix-blend-mode: luminosity)') |
Поддержка в браузерах
Все современные браузеры кроме IE11 и Opera Mini поддерживают правило @supports. Готово ли правило @supports к выходу в свет? Самый лучший ответ я нашел у Tiffany Brown:
«… с осторожностью подходите к задаче применения критически важных стилей через @supports… Определите базовые стили – стили, которые поддерживаются всеми браузерами. Затем, используйте @supports для того, чтобы переписать или дополнить те стили, которые можно записать в браузерах с помощью новых свойств. CSS Master, p.303»
Заключение
В данной статье я исследовала нативный CSS метод определения поддержки свойств через правило @supports. Также было рассмотрено соответствующее JS API, с помощью которого можно проверить текущую поддержку браузером последних CSS свойств при помощи гибкого метода Css.supports().
Поддержка CSS запросов довольно хорошая, однако не повсеместная. Но все же, если вы хотите использовать @supports в своих проектах, вам может помочь стратегическое размещение стилей в CSS файле, как было сказано Tiffany Brown, а также css-supports.js polyfill от Han Lin Yap.
Если вы посмотрели демо к статье и у вас появились вопросы, или у вас уже был опыт использования @supports, пишите об этом в комментариях.
Автор: Maria Antonietta Perna
Источник: //www.sitepoint.com/
Редакция: Команда webformyself.

Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
Узнать подробнее