Статьи

Введение в правило @supports CSS (запросы функций)

Два основных подхода к решению проблемы неравномерной поддержки браузерами новейших технологий — это постепенная деградация и прогрессивное улучшение .

Изящная деградация использует передовые технологии для разработки сложных пользовательских функций и функциональности. Пользователи менее способных браузеров по-прежнему будут иметь доступ к веб-сайту, но будут пользоваться сниженным уровнем функциональности и удобством просмотра.

С прогрессивным улучшением разработчики устанавливают базовый уровень, разрабатывая для уровня пользовательского опыта, который может поддерживать большинство браузеров. Их приложения обеспечивают встроенное обнаружение возможностей браузеров, которые они используют, чтобы сделать доступными более продвинутые функциональные возможности и соответственно более богатые возможности просмотра.

Наиболее распространенным инструментом в подходе прогрессивного улучшения является библиотека Modernizr JavaScript.

Modernizr программно проверяет, поддерживает ли браузер веб-технологии следующего поколения, и, соответственно, возвращает true или false . Вооружившись этими знаниями, вы можете использовать новые функции поддержки браузеров и при этом иметь надежные средства обслуживания старых или несовместимых браузеров.

Как бы хорошо это ни звучало, что-то еще лучше назревает в течение некоторого времени. Вы можете выполнить обнаружение функций с помощью собственных запросов к функциям CSS с помощью правила @supports .

В этом посте я собираюсь углубиться в @supports и связанный с ним JavaScript API.

Определение функций браузера с @supports правила @supports

Правило @supports является частью спецификации условных правил CSS3 , которая также включает в себя более распространенное правило @media мы все используем в наших @supports .

Хотя с помощью медиа-запросов вы можете обнаруживать такие функции отображения, как ширина и высота области просмотра, @supports позволяет проверять поддержку браузером пар свойство / значение CSS .

Давайте рассмотрим базовый пример. Допустим, на вашей веб-странице отображается произведение искусства, которое вы хотели бы улучшить с помощью смешивания CSS . Это правда, режимы наложения CSS изящно ухудшаются в не поддерживающих браузерах. Однако вместо того, что браузер отображает по умолчанию в таких случаях, вы можете порадовать пользователей не поддерживающих браузеров отображением чего-то такого же особенного, если не столь впечатляющего. Вот как вы должны выполнить проверку наложения CSS в вашей таблице стилей с помощью @supports :

 @supports (mix-blend-mode: overlay) { .example { mix-blend-mode: overlay; } } 

Чтобы применить разные стили для браузеров, которые не поддерживают mix-blend-mode , используйте следующий синтаксис:

 @supports not(mix-blend-mode: overlay) { .example { /* alternative styles here */ } } 

Несколько вещей, на которые стоит обратить внимание:

  • Условие, которое вы тестируете, должно быть в скобках. Другими словами, @supports mix-blend-mode: overlay { ... } недопустим. Однако, если вы добавите больше скобок, чем нужно, код будет в порядке. Например, @supports ((mix-blend-mode: overlay)) допустим.
  • Условие должно включать как свойство, так и значение. В приведенном выше примере вы проверяете свойство mix-blend-mode и значение overlay для этого свойства.
  • Добавление конечного символа !important объявление, которое вы тестируете, не повлияет на достоверность вашего кода.

Давайте дополним приведенные выше примеры небольшой демонстрацией. Браузеры с поддержкой mix-blend-mode будут применять стили внутри @supports() { ... } ; другие браузеры будут применять стили внутри @supports not() { ... } .

HTML:

 <article class="artwork"> <img src="myimg.jpg" alt="cityscape"> </article> 

CSS:

 @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 оператор соединения проверяет наличие нескольких обязательных условий:

 @supports (property1: value1) and (property2: value2) { element { property1: value1; property2: value2; } } 

Используя дизъюнктивный or ключевое слово, вы можете проверить наличие нескольких альтернативных функций для набора стилей. Это особенно удобно, если для некоторых из этих альтернатив требуются префиксы поставщиков для их свойств или значений:

 @supports (property1: value1) or (-webkit-property1: value1) { element { -webkit-property1: value1; property1: value1; } } 

Вы также можете комбинировать and с or , условия тестирования в том же @supports :

 @supports ((property1: value1) or (-webkit-property1: value1)) and (property2: value2) { element { -webkit-property1: value1; property1: value1; property2: value2; } } 

Когда вы группируете несколько условий вместе, правильное использование скобок имеет решающее значение. Объединение and , or , а not ключевых слов вместе не будет работать. Кроме того, способ, которым вы группируете условия в скобках, устанавливает порядок их оценки. В приведенном выше фрагменте сначала вычисляется дизъюнктивный or условия, а затем полученный ответ сравнивается с дополнительным обязательным условием, введенным ключевым словом and .

Как сгруппировать условия для нескольких проверок

Ключевое слово not позволяет вам проверять одно условие за раз. Например, приведенный ниже код недействителен:

 @supports not (property1: value1) and (property2: value2) { /* styles here... */ } 

Вместо этого вам нужно сгруппировать все условия, которые вы отрицаете, с ключевым словом not в скобках. Вот исправленная версия фрагмента выше:

 @supports not ((property1: value1) and (property2: value2)) { /* styles here... */ } 

Наконец, убедитесь, что вы оставляете пустое пространство после not и с обеих сторон от and или or .

Операторы в действии

Вы можете применить набор стилей, если браузер поддерживает как градиенты, так и режимы наложения, используя следующий синтаксис (я разбил приведенный ниже код на несколько строк для отображения):

 @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 :

 @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 :

 @supports not ( (mix-blend-mode: luminosity) and (mix-blend-mode: saturation) ) { .artwork img { mix-blend-mode: overlay; } } 

Все демонстрационные материалы для этого раздела доступны на CodePen:

JavaScript с CSS-запросами

Вы можете воспользоваться преимуществами CSS Feature Queries, используя JavaScript CSS Interface и функцию supports() . Вы можете написать Css.supports() одним из двух способов.

Предыдущий и наиболее широко поддерживаемый синтаксис принимает два аргумента, то есть свойство и значение , и возвращает логическое значение true или false :

 CSS.supports('mix-blend-mode', 'overlay') 

Убедитесь, что вы поместили свойство и его соответствующее значение в кавычки. Спецификация проясняет, что вышеуказанная функция возвращает true если она удовлетворяет следующим двум условиям:

  • Свойство является «буквальным соответствием имени свойства CSS», которое поддерживает браузер;
  • Значение будет «успешно проанализировано как поддерживаемое значение для этого свойства».

Под буквальным соответствием спецификация означает, что экранирование CSS не обрабатывается и пробелы не обрезаются. Поэтому не экранируйте символы и не оставляйте завершающий пробел, иначе тест вернет false .

Альтернативный, более новый синтаксис принимает только один аргумент в скобках:

 CSS.supports('(mix-blend-mode: overlay)') 

Использование этого синтаксиса делает удобным тестирование нескольких условий с помощью ключевых слов and и or .

Вот быстрый пример. Допустим, вы хотите проверить, поддерживает ли браузер режим наложения luminosity . Если это произойдет, ваш JavaScript будет динамически добавлять класс luminosity-blend к целевому элементу, в противном случае он добавит класс noluminosity . Ваш CSS будет соответствующим образом стилизовать элемент.

Вот CSS:

 .luminosity-blend { mix-blend-mode: luminosity; } .noluminosity { mix-blend-mode: overlay; } 

Если вы используете синтаксис с двумя аргументами, фрагмент JavaScript может выглядеть следующим образом:

 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); 

Если вы предпочитаете новейший синтаксис с одним аргументом, просто замените соответствующую строку кода выше на следующую:

 var test = CSS.supports('(mix-blend-mode: luminosity)') 

Не стесняйтесь проверить демо:

Поддержка браузера

Все последние версии основных браузеров поддерживают правило @supports, за исключением Internet Explorer 11 и Opera Mini. Готова ли @supports к реальному миру? Я нашел лучший ответ на этот вопрос в словах Тиффани Браун:

… будьте осторожны с определением критических стилей в @supports …
Определите ваши базовые стили — стили, на которые нацелены все ваши
браузеры могут справиться. Затем используйте @supports …, чтобы переопределить и дополнить
те стили в браузерах, которые могут обрабатывать новые функции.

Мастер CSS , стр.303

Вывод

В этой статье я рассмотрел обнаружение встроенных функций браузера CSS с @supports правила @supports (также называемого запросами функций). Я также прошел через соответствующий API-интерфейс JavaScript, который позволяет вам проверять текущее состояние поддержки браузером последних свойств CSS, используя гибкий Css.supports() .

Поддержка браузером запросов к функциям CSS хороша, но не охватывает все ваши основы. Однако, если вы хотите использовать @supports в своих проектах, вам может @supports стратегическое размещение стилей в вашем CSS-документе, как предлагает Тиффани Браун, и полизаполнение css-support.js Хана Лин Япа.

Если вы опробовали демоверсии в этой статье или имели реальный опыт использования @supports , я бы хотел услышать ваше @supports .