Статьи

Совет: обнаружение поддержки CSS3 в браузерах с помощью JavaScript

Разве не забавно, что мы играем с новейшими техниками CSS, такими как тени и переходы? Есть только одна проблема: как мы компенсируем или, что более важно, обнаруживаем браузеры, которые их не поддерживают? Ну, есть несколько решений. В этом уроке и скринкасте мы создадим функцию JavaScript, которая будет принимать имя свойства CSS в качестве параметра и будет возвращать boolean , указывающее, поддерживает ли браузер переданное свойство.


Нажмите кнопку HD для более четкого изображения.

Подпишитесь на нашу страницу YouTube, чтобы посмотреть все видеоуроки!


Давайте начнем с определения того, как мы хотим вызвать нашу function . Здесь все будет просто; что-то вроде следующего должно сделать свое дело:

1
2
3
if ( supports(‘textShadow’) ) {
   document.documentElement.className += ‘ textShadow’;
}

Это должен быть последний вызов function . Когда мы передаем имя свойства CSS в функцию supports() , оно возвращает boolean . Если true , мы прикрепим className к documentElement или <html> . Затем мы получим новое имя `class` для подключения из нашей таблицы стилей.


Далее мы создадим supports() function .

1
2
3
var supports = (function() {
 
})();

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


Чтобы проверить, поддерживает ли браузер определенные свойства, нам нужно создать элемент * dummy * для тестирования. Этот сгенерированный элемент никогда не будет вставлен в DOM; думать об этом как о манекене!

1
var div = document.createElement(‘div’);

Как вы, вероятно, знаете, есть несколько префиксов поставщиков, которые мы можем использовать при работе со свойствами CSS3:

  • -moz
  • -webkit
  • -Миз
  • -khtml

Наш JavaScript должен будет отфильтровать эти префиксы и протестировать их. Итак, давайте разместим их в array ; мы назовем это, vendors .

1
2
var div = document.createElement(‘div’),
    vendors = ‘Khtml Ms O Moz Webkit’.split(‘ ‘);

Использование функции split() для создания array из string по общему признанию, лениво, но экономит несколько секунд!

Поскольку мы будем фильтровать этот array , давайте будем хорошими парнями и девочками, а также кешируем length array .

1
2
3
var div = document.createElement(‘div’),
  vendors = ‘Khtml Ms O Moz Webkit’.split(‘ ‘),
  len = vendors.length;

Подготовительная работа, приведенная выше, является статической по своей природе, и ее не нужно повторять каждый раз, когда мы вызываем supports() . Вот почему мы запускаем его только один раз, когда страница загружается. Теперь давайте return function которая будет фактически назначена variable .

1
2
3
return function(prop) {
 
};

Прелесть closures в том, что, хотя supports() равна возвращаемой function , она все еще имеет доступ к переменным div , vendors и len .


Непосредственный тест: если переданное свойство доступно атрибуту style div , мы знаем, что браузер поддерживает это свойство; так return true .

1
2
3
return function(prop) {
   if ( prop in div.style ) return true;
};

Представьте, скажем, свойство CSS3 text-shadow . Большинство современных браузеров поддерживают его без необходимости использования префикса поставщика. Имея это в виду, зачем фильтровать все префиксы, если нам это не нужно? Вот почему мы размещаем этот чек сверху.


Скорее всего, вы привыкли вводить имена свойств CSS3, например: -moz-box-shadow . Однако, если в Firebug вы MozBoxShadow object style , вы обнаружите, что он записан как MozBoxShadow . Таким образом, если мы проверим:

1
‘mozboxShadow’ in div.style // false

False будет возвращена. Это значение чувствительно к регистру.

Деликатный случай

Это означает, что, если пользователь передаст boxShadow функции boxShadow supports() , boxShadow сбой. Давайте подумаем и проверим, является ли первая буква аргумента строчной. Если это так, мы исправим ошибку для них.

1
2
3
4
5
6
7
8
return function(prop) {
   if ( prop in div.style ) return true;
 
   prop = prop.replace(/^[az]/, function(val) {
      return val.toUpperCase();
   });
 
};

Регулярные выражения на помощь! Выше мы проверяем, есть ли одна строчная буква в начале строки ( ^ ). Только при условии, что он найден, мы используем функцию toUpperCase() чтобы заглавные буквы.


Затем нам нужно отфильтровать массив vendors и проверить, есть ли совпадение. Например, если передано box-shadow , мы должны проверить, содержит ли атрибут style div любое из следующего:

  • MozBoxShadow
  • WebkitBoxShadow
  • MsBoxShadow
  • OBoxShadow
  • KhtmlBoxShadow

Если совпадение найдено, мы можем return true , потому что браузер действительно предоставляет поддержку для теней блоков!

01
02
03
04
05
06
07
08
09
10
11
12
13
return function(prop) {
   if ( prop in div.style ) return true;
 
   prop = prop.replace(/^[az]/, function(val) {
      return val.toUpperCase();
   });
 
   while(len—) {
      if ( vendors[len] + prop in div.style ) {
            return true;
      }
   }
};

Хотя мы могли бы использовать оператор for для фильтрации array , в этом нет особой необходимости.

  • Порядок не важен
  • while операторы быстрее набираются и требуют меньше символов
  • Есть небольшое улучшение производительности

Не смущайтесь vendors[len] + prop ; просто замените эти имена их реальными значениями: MozBoxShadow .


Но что, если ни одно из этих значений не совпадает? В этом случае браузер не поддерживает свойство, и в этом случае мы должны return false .

1
2
3
4
5
6
while(len—) {
   if ( vendors[len] + prop in div.style ) {
         return true;
   }
}
return false;

Это должно сделать это для нашей функции! Давайте проверим это, применив className к элементу html , если браузер поддерживает, скажем, свойство text-stroke (что делает только webkit).

1
2
3
if ( supports(‘textStroke’) ) {
   document.documentElement.className += ‘ textStroke’;
}

С именем class которое мы теперь можем подключить , давайте попробуем это в нашей таблице стилей.

01
02
03
04
05
06
07
08
09
10
/* fallback */
h1 {
   color: black;
}
 
/* text-stroke support */
.textStroke h1 {
  color: white;
  -webkit-text-stroke: 2px black;
}

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var supports = (function() {
   var div = document.createElement(‘div’),
      vendors = ‘Khtml Ms O Moz Webkit’.split(‘ ‘),
      len = vendors.length;
 
   return function(prop) {
      if ( prop in div.style ) return true;
 
      prop = prop.replace(/^[az]/, function(val) {
         return val.toUpperCase();
      });
 
      while(len—) {
         if ( vendors[len] + prop in div.style ) {
            // browser supports box-shadow.
            // Or use a bang (!) to test if the browser doesn’t.
            return true;
         }
      }
      return false;
   };
})();
 
if ( supports(‘textShadow’) ) {
   document.documentElement.className += ‘ textShadow’;
}

Для более полного решения обратитесь к библиотеке Modernizr .