@supports изменит вашу жизнь

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

При использовании новых возможностей CSS часто не приходится заботиться о запасном варианте — CSS делает это за нас. CSS всепрощающий, он игнорирует строки кода, которые не понимает. Так, браузеры просто не будут применять свойство, которое они не поддерживают. Давайте рассмотрим это на примере.

CSS-фигуры (shapes)

Фигуры (CSS Shapes) это просто и красиво, и их очень легко использовать, если браузер их поддерживает. Можно сделать обтекание текстом круглого изображения, например так:

Скриншот

Вот код примера. Обратите внимание на свойство shape-outside:

.shape {
  width: 20em;
  height: 20em;
  float: left;
  margin: 1em 2em 1em 0;
  border-radius: 25em;
  shape-outside: circle(50%);
}

На прошлой неделе поддержка браузерами свойства shape-outside составляла 65%, так что она не идеальна, но это не имеет значения. Результат выглядит хорошо и в браузерах, которые не поддерживают свойство shape-outside. Мы просто увидим текст, который обтекает изображение по прямой, мы к такому привыкли.

Скриншот

Этот подход позволяет использовать множество новых CSS-свойств, но не все. Как насчет более сложного CSS, который уже не выглядит так хорошо в старых браузерах? В качестве примера рассмотрим режимы наложения.

Режимы наложения (blend modes)

Когда я в последний раз проверял caniuse (на этой неделе), 72% браузеров поддерживали background-blend-modes.

CSS может выглядеть следующим образом:

.wrapper {
    background-image: 
    linear-gradient(lightblue 0%, pink 100%), linear-gradient(to right, pink 30%, white 100%), url("https://c7.staticflickr…"); 
    …
    background-blend-mode: hue;
}

Есть несколько фоновых изображений: одна картинка и два линейных градиента. Мы применяем к ним режим наложения. Вот что можно увидеть в 72% браузеров:

Фото горы с градиентом и текстом

А вот что вы увидите в браузерах, которые не поддерживают режимы наложения:

Фото, на котором не видно горы, так как не поддерживаются режимы наложения

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

Но не спешите ставить крест на режимах наложения! Мы всё же можем использовать их в продакшене. Для этого есть очень мощный инструмент, который может изменить вашу жизнь. Он называется @supports.

@supports

Директива @supports позволяет написать условное выражение, проверяющее поддержку определенного CSS-свойства и применяющее блок кода в зависимости от результата проверки. Иногда это называют Feature Query.

Она очень похожа на медиавыражения:

@supports (background-blend-mode: hue) {
   /* Этот код выполнится только если браузер поддерживает background-blend-mode: hue */
}

В первой строке мы пишем @supports и условие. В этом примере условие в скобках означает следующее: если background-blend-mode: hue; поддерживается, нужно применить указанные в фигурных скобках правила. Если этот режим наложения не поддерживается, то правила применять не нужно.

Вот как @supports позволяет использовать режим наложения в продакшене:

.wrapper {
    background-image: url("https://c7.staticflickr…");  
}

@supports (background-blend-mode: hue) {
    .wrapper {
        background-image: linear-gradient(lightblue 0%, pink 100%),
        linear-gradient(to right, pink 30%, white 100%), url("https://c7.staticflickr.com/2/1510/…");  
        background-blend-mode: hue;
    }
}

Стили для класса .wrapper вне @supports применятся любым браузером. Все браузеры как минимум отобразят фоновое изображение. Стили внутри @supports применят только браузеры, которые поддерживают background-blend-mode: hue;. Ниже обновлённый пример кода в браузерах, которые не поддерживают режимы смешивания. Выглядит намного лучше, и определенно можно использовать в продакшене:

Фото горы с текстом без градиента, если режимы наложения не поддерживаются

Поддержка @supports браузерами

Здорово, но что насчет поддержки @supports браузерами? На момент написания статьи его поддерживают 77% браузеров. Поддержки нет в IE и Opera Mini (в Opera Mini уже есть — Прим. ред.). Что произойдет, если @supports не поддерживается? Тогда браузер просто проигнорирует содержащийся в теле директивы код, что хорошо.

Рассмотрим наш предыдущий пример. Это то, что мы получаем, когда @supports не поддерживается. Точно такие же результаты, как и раньше, потому что браузер не применяет какой-либо из стилей внутри запроса @supports.

Фото горы с текстом без градиента, если @supports не поддерживаются

CSS-фигуры и @supports

Теперь мы можем улучшить пример использования CSS-фигур, приведенный ранее. Помните как текст обтекает круглое изображение, когда shape-outside поддерживается? И как текст обтекает то же изображение в браузерах без поддержки shape-outside?

Теперь мы можем сказать браузеру, что даже если он поддерживает border-radius, применять его нужно только при поддержке свойства shape-outside:

.shape{
    width: 20em;
    height: 20em;
    float: left;
    margin: 0.25em 2em 1em 0;
}

@supports (shape-outside: circle()) {
    .shape {
        shape-outside: circle(50%);
        border-radius: 25em;
    }    
}

Таким образом, когда браузер поддерживает свойство shaped-outside вы увидите пример слева, а когда не поддерживает — справа. Так-то лучше!

CSS shapes with supports

Условия можно объединять в цепочки с помощью or и and. Если вы хотите быть максимально осторожны, можно добавить еще одно условие, чтобы быть на 100% уверенным, что border-radius тоже поддерживается:

.shape{
    width: 20em;
    height: 20em;
    float: left;
    margin: 0.25em 2em 1em 0;
}

@supports (border-radius: 25em) and (shape-outside: circle()) {
    .shape {
        shape-outside: circle(50%);
        border-radius: 25em;
    }    
}

Или, возможно, вы захотите использовать not, чтобы стили применились только в том случае, если условие не выполнено:

@supports not (shape-outside: circle()) {
    .shape {
        /* Стили применяться только если shape-outside не поддерживается */
    }    
}

Традиционно мы использовали modernizr, чтобы определить поддержку свойств браузерами. Это работает, но без JavaScript всё будет ещё лучше. Modernizr может быть и небольшой, но он всё равно должен загрузиться до того, как будут применены правила CSS. И всегда есть некоторый риск, что JavaScript по какой-то причине не выполнится.

Я в восторге от @supports. Это очень мощный инструмент. Думаю, в будущем при написании CSS мы будем использовать его очень и очень часто.