Статьи

Разрезание горчицы с помощью CSS Media Queries

Сокращение Горчицы — термин, придуманный Томом Масленом на Би-би-си. Метод использует JavaScript, который проверяет возможности браузера перед загрузкой дополнительных CSS и JavaScript, чтобы дать пользователю «расширенный» опыт, в противном случае браузер будет загружать только файлы, необходимые для «основного» опыта.

В последнее время наблюдается интерес к срезанию горчицы, например, « Миграция на Flexbox» с помощью среза «Горчица» и « Срез на горчице на стороне сервера» , а также в Прогрессивное улучшение в целом.

Делать лучше

Однако, по моему опыту, даже очень простой «базовый» опыт может вызвать проблемы в некоторых очень старых браузерах, поэтому я хотел бы развить эту идею и посмотреть, можно ли вообще запретить действительно старым браузерам какой-либо CSS, оставив их с только HTML.

Конечно, очевидное решение состоит в том, чтобы использовать JavaScript для условной загрузки всего CSS, если браузер режет горчицу, но мне это показалось слишком сложным; современные, способные браузеры, которые не загружают JavaScript, будут оштрафованы отсутствием стилей вообще. Поэтому я искал подход к проблеме только с помощью CSS и нашел старый пост Крейга Баклера . После долгих экспериментов и адаптации я придумал следующее:

<!-- in the <head> -->
<link rel="stylesheet" href="css/your-stylesheet.css"
      media="only screen and (min-resolution: 0.1dpcm)">
<link rel="stylesheet" href="css/your-stylesheet.css" 
      media="only screen and (-webkit-min-device-pixel-ratio:0) 
      and (min-color-index:0)">

Давайте рассмотрим, что здесь происходит.

Как это устроено

Медиа-запрос первого элемента <link>

  • IE 9+
  • FF 8+
  • Опера 12
  • Chrome 29+
  • Android 4.4+

Медиа-запрос второго элемента <link>

  • Chrome 29+
  • Опера 16+
  • Safari 6.1+
  • iOS 7+
  • Android 4.4+

В сочетании этот метод не будет загружать таблицу стилей, если браузер не:

  • IE 9+
  • FF 8+
  • Опера 12, 16+
  • Chrome 29+
  • Safari 6.1+
  • iOS 7+
  • Android 4.4+

Примечание: таблица стилей загружается только один раз, независимо от количества элементов <link>

Можно объединить медиазапросы в один элемент ссылки, разделив объявления запятой, например:

 <link rel="stylesheet" href="css/your-stylesheet.css"
      media="only screen and (min-resolution: 0.1dpcm),
      only screen and (-webkit-min-device-pixel-ratio:0)
      and (min-color-index:0)">

Однако мне лично нравится держать их отдельно, так как мне легче видеть, что происходит.

Таким образом, если вы структурируете разметку семантическим и доступным способом, старые браузеры по-прежнему должны видеть ваш не стилизованный контент в обычном HTML.

Это, конечно, очень самоуверенно, но я считаю, что любой, кто использует эти браузеры, все еще заслуживает того, чтобы получить то, что ему нужно. Вполне вероятно, что, предоставив этим браузерам CSS, предназначенный для новых браузеров, некоторые вещи просто сломаются, и это может означать совершенно непригодную страницу. Используя этот метод, они по крайней мере получают чистый лист. Что еще более важно, вам больше никогда не придется тестировать в этих браузерах . Вы сделали с ними! По крайней мере, это теория.

Конечно, ваши потребности в поддержке могут варьироваться, но самое замечательное в этой технике — то, что вы можете на ней опираться. Например, если вам нужно добавить поддержку IE8, вы можете использовать условный комментарий, чтобы загрузить ту же таблицу стилей только для этого браузера:

 <!--[if IE 8]>
<link rel="stylesheet" href="css/your-stylesheet.css">
<![endif]-->

Или, если вам нужно поддерживать более старые устройства WebKit с соотношением пикселей более 1, вы можете добавить еще один элемент <link>

 <link rel="stylesheet" href="css/your-stylesheet.css"
      media="only screen and (-webkit-min-device-pixel-ratio:1.1)">

Само по себе это приведет к загрузке таблицы стилей только для Android 2.2+ (я не смог протестировать более ранние версии), но, поскольку она включена в дополнение к другим элементам <link>

Также возможно, что вы можете изменить медиа-запросы основного элемента <link> Однако, чтобы понять это правильно, потребовалось немало испытаний, так что будьте осторожны!

«Но они хаки!»

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

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

Где это не работает

Во всех моих тестах на сегодняшний день я обнаружил только один случай, когда все работает не так, как ожидалось. На Android 4.4 UC Browser не отвечает на медиа-запрос. Из того, что я могу сказать, UC Browser использует более старую версию WebKit, которая объясняет вещи.

Если вы хотите поддержать этот браузер, можно прибегнуть к небольшому анализу пользовательского агента, чтобы заставить CSS загружаться:

 if (navigator.userAgent.indexOf('UCBrowser') > -1) {
  var link  = document.createElement('link');
  link.rel  = 'stylesheet';
  link.href = 'css/your-stylesheet.css';
  document.getElementsByTagName('head')[0].appendChild(link);
}

В качестве бонуса, насколько я могу судить, невозможно отключить JavaScript в браузере Android UC, поэтому всегда следует загружать таблицу стилей, исключая сбои сети и тому подобное.

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

Я сделал тестовую страницу, чтобы протестировать базовый метод в разных браузерах. Если вы обнаружите браузеры, в которых все работает не так, как ожидалось, или если вы обнаружите какие-либо другие медиазапросы, которые могут добавить поддержку определенного браузера или диапазона браузеров, пожалуйста, сообщите мне об этом в комментариях или поднимите вопрос о репозитории GitHub. ,

А как насчет загрузки скриптов?

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

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

  • В вашей таблице стилей вставьте безвредное нестандартное свойство CSS в элемент body
  • Используйте JavaScript и getComputedStylebody
  • Если это так, запустите или загрузите другой JavaScript.

Например, свойство clearnone Установка его bothbody Таким образом, код будет выглядеть так в вашей таблице стилей:

 body {
  clear: both;
}

И на вашей странице (или в файле скрипта):

 var is_supported = false
  , val = '';
if (window.getComputedStyle) {
  val = window.getComputedStyle(document.body, null).getPropertyValue('clear');
} else if (document.body.currentStyle) {
  val = document.body.currentStyle.clear;
}

if (val == 'both') {
  is_supported = true;
}

Окончательный код

Хак или нет, то, что я попытался показать здесь, — это многократно используемый способ обнаружения относительно современного браузера и запрета старым браузерам применять стили или запускать скрипты, заставляя их отображать только HTML-код вашей страницы. Требуемый код довольно минимален, и он должен позволить вам сконцентрировать свои усилия на создании замечательных вещей для более современных браузеров, используя более современные методы, не беспокоясь.

Хотя вам, возможно, и не понадобится все, что я здесь представил, соединение всех частей дает нам следующее:

 <head>
  <link rel="stylesheet" href="mq-test.css"
        media="only screen and (min-resolution: 0.1dpcm)">
  <link rel="stylesheet" href="mq-test.css"
        media="only screen and (-webkit-min-device-pixel-ratio:0)
        and (min-color-index:0)">
  <link rel="stylesheet" href="mq-test.css"
        media="only screen and (-webkit-min-device-pixel-ratio:1.1)">

  <!--[if IE 8]>
  <link rel="stylesheet" href="mq-test.css">
  <![endif]-->

  <script>
    if (navigator.userAgent.indexOf('UCBrowser') > -1) {
      var link  = document.createElement('link');
      link.rel  = 'stylesheet';
      link.href = 'mq-test.css';
      document.getElementsByTagName('head')[0].appendChild(link);
    }
  </script>
</head>
<body>
<!-- content here... -->
  <script>
    var is_supported = false
      , val = '';
    if (window.getComputedStyle) {
      val = window.getComputedStyle(document.body, null).getPropertyValue('clear');
    } else if (document.body.currentStyle) {
      val = document.body.currentStyle.clear;
    }

    if (val == 'both') {
      is_supported = true;
    }

    if (is_supported) {
      // Load or run JavaScript for supported browsers here.
    }
  </script>
</body>

Я сделал еще одну тестовую страницу со всеми дополнениями .

кредиты

Я не смог бы сделать это без использования BrowserStack , Can I Use и работы ребят из Browserhacks и Jeff Clayton , так что спасибо всем, кто в этом участвует, и, пожалуйста, дайте мне знать, если у вас есть какие-либо мысли или отзывы.