Различение браузеров
Нередко перед веб-программистом стоит задача выделить какой-либо браузер или некоторую конкретную версию какого-либо браузера из всех остальных. Чаще всего речь идет, конечно, об Internet Explorer’е и в частности его шестой версии. После того, как название и версия браузера определены, пользователю, который его использует, можно показать некоторую специфическую страницу (например, извещающую о невозможности работы сайта в IE6), передать дополнительные CSS-правила стилей, необходимые для правильного отображения посетителю страницы или, скажем, выполнить на странице некоторый JavaScript-код.
Методы различения браузеров по характеру их использования можна разделить на три категории: различение браузера на стороне севера и выдача специфичного ответа; различение на стороне клиента с помощью JavaScript и дальнейшим использованием специфичного JS-скрипта; формирование «хитрого» HTML- или CSS-кода, который разные браузеры интерпретируют по-своему. Проведем краткий обзор каждого из названных методов.
Определение браузера на стороне сервера
Браузер передает на сервер в виде строки базовую информацию о себе и об операционной системе, в которой работает. В частности, доступ к такой информации имеет скрипт, который генерирует веб-страницу. В PHP переданная строка сохраняется как элемент $_SERVER['HTTP_USER_AGENT'] массива $_SERVER. Каждый браузер формирует такую строку по собственному усмотрению. Вот несколько примеров строк для разных браузеров и разных ОС:
Mozilla/5.0 (Windows; U; Windows NT 5.1; uk; rv:1.9.2.8)
Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729)
Firefox 3.6.8, Windows XP
Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.9
(KHTML, like Gecko) Chrome/5.0.307.9 Safari/532.9
Chrome 5.0, Linux Ubuntu
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)
Internet Explorer 8, Windows 7
Opera/9.80 (X11; Linux i686; U; en) Presto/2.6.30 Version/10.61
Opera 10.61, Linux Debian
Значительно больший список разнообразных строк идентификации, которые были собраны «в полевых условиях», можно найти на ресурсе Useragentstring.com.
Хоть определенного формата строка идентификации браузера не имеет, можно быть уверенным на 99 % и полагаться на то, что как текущие, так и будущие версии наиболее распространенных браузеров будут формировать эту строку так, что:
- В строке будут присутствовать (как подстроки) названия самого браузера (в случае с Internet Explorer’ом название сокращено — MSIE) и движка, на котором он базируется: например, Trident для IE, Presto для Оперы, WebKit для Хрома и Сафари, Gecko для Файрфокса. Следует заметить, однако, что Хром, ради пущей совместности со старыми сайтами, указывает в строке идентификации и родственный браузер Safari, и менее родственный движок Gecko, и в перспективе это может быть не единственным подобным случаем.
- Через слеш после названия движка и названия самого браузера будут указываться их версии. Исключением является Internet Explorer, версия которого указывается через пробел после сокращенного названия MSIE. Также временно не придерживается формата браузер Opera — из-за проблем с совместимостью. В случае с Оперой, по крайней мере для версий 10.*, настоящая версия указывается через слеш после слова «Version».
- Если браузер работает на платформе Windows, в строке будет присутствовать слово «Windows»; если на Линуксе — «Linux».
Соответственно, чтобы определить, какой браузер использует посетитель, необходимо обработать строку идентификации. Если стоит задача выделить конкретную или набор из нескольких конкретных версий браузеров, можно попробовать искать соответственную подстроку или проверить строку идентификации на соответствие регулярному выражению.
01
02
03
04
05
06
$isPresto = strpos($_SERVER['HTTP_USER_AGENT'],'Presto')!==false; $isOldIE = preg_match('|(?<!\w)MSIE [1-7](?!\w)|',$_SERVER['HTTP_USER_AGENT'])>0; preg_match('|(?<!\w)Firefox/([\d\.]+)|',$_SERVER['HTTP_USER_AGENT'],$matches); $FirefoxVersion = isset($matches[1])?$matches[1]:false;
Тут первая строка определяет, работает ли браузер на движке Presto. Вариант не идеальный, так как — кто знает — когда-нибудь может выйти новый браузер с названием вроде «Prestoria», никак не связанный с Presto. Чтобы избавиться от этого недочета, нужно использовать регулярное выражение. Так, в третьей строке с помощью регулярного выражения определяется, не есть ли, чего доброго, браузер Internet Explorer’ом седьмой, шестой или, не дай боже, еще более ранней версии. Наконец, в последних двух строках определяем версию Файрфокса (переменная $FirefoxVersion будет содержать false, если браузер — не Файрфокс).
Если же задача по различению стоит более серьезная и то, какой используется браузер, нужно анализировать подробнее, можно воспользоваться функцией PHP get_browser() или сторонней библиотекой, как, например, Browser.php. Последняя позволяет, в частности, вызвав специальный метод, определить, зашел ли пользователь на сайт с мобильного устройства (то есть, запущен ли браузер на мобильном устройстве), или то, что данное посещение страницы совершает поисковый робот вроде Гугла. Каждый из этих вариантов использует все тот же подход: разбирает строку-идентификатор.
Определение браузера с помощью JavaScript
Та же строка-идентификатор браузера, которая передавалась на сервер, доступна и из окружения JavaScript. А если конкретнее, ее можно получить, считав значение переменной navigator.userAgent. Далее работают в точности те же приемы, что и для серверного варианта.
К счастью, объект navigator кроме строки-идентификатора содержит также и некоторые другие параметры браузера, что облегчает определение его названия и версии. Так, параметр navigator.appName должен содержать имя браузера, а navigator.appVersion — его версию. К сожалению, такие браузеры, как Firefox, Chrome, Safari (с той же целью совместимости) в appName указывают Netscape, а в appVersion — мифическую «версию совместимости с Mozilla», которая не имеет прямого отношения к настоящей. Опера правильно указывает свое название, но, как и в случае со строкой-идентификатором, может указать неправильную версию. Неправильную версию указывает пока и IE (зато имя свое пишет полностью — «Microsoft Internet Explorer»). Единственное, на что можно полагаться, — это платформа. Ее задает параметр navigator.platform.
01
02
03
alert('Строка-идентификатор:\n' + navigator.userAgent + '\n\nНазвание/тип браузера: ' + navigator.appName + '\n\nПлатформа: ' + navigator.platform);
Испробуйте этот код:
Для более точного распознавания браузеров на стороне клиента написаны соответствующие скрипты, которые подробно анализируют строку-идентификатор. Один из таких скриптов можно скопировать из соответственной статьи на сайте Quirksmode.org.
«Хитрый» CSS
Набор методов, которые базируются на «запутывании» таблиц стилей (или даже разметки) так, что разные браузеры трактуют их по-разному, получил название CSS-хаков. CSS-хаки возможны благодаря тому, что браузеры неидеально поддерживают разнообразные стандарты (то есть, фактически хаки питаются ошибками браузеров). Скажем, IE6 позволяет обратиться в стилях к элементу html как к «* html», в то время как более новые версии IE и другие браузеры такого синтаксиса не понимают. Вместе с тем, IE6, в отличие от других, не понимает «html>body». С помощью такого рода элементов можно сконструировать достаточно гибкие правила, которые будут различаться для разных браузеров, когда это необходимо.
Если просто выделить один браузер из других — задача, решение которой сильно зависит от конкретной реализации каждого из браузеров и делать это рекомендуется только в том случае, если ни один другой способ не помог, то решать эту задачу с помощью CSS-хаков в силу их чрезвычайной хрупкости в наше время вообще недопустимо.
Условные комментарии
Условные комментарии — это «легальные» CSS-хаки, которые используют синтаксис, специально вложенный в IE разработчиками, чтобы дать возможность веб-разработчикам выделить IE, или даже его отдельные версии, из других браузеров.
Условные комментарии формально являются обычными комментариями в HTML-коде страницы, но их специфический синтаксис дает знать отдельным версиям Internet Explorer’а, что то, что написано в комментарии, нужно расценивать как настоящий HTML. Или наоборот — настоящий HTML-текст мужду двумя комментариями не принимать во внимание, как будто его никогда и не было. Рассмотрим синтаксис на нескольких примерах:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<!--[if IE]> <p><i>Этот текст увидят только пользователи IE.</i></p> <![endif]--> <!--[if IE 6]> <link rel="stylesheet" type="text/css" href="/styles/ie6.css" /> <script type="text/javascript" src="/scripts/ie6.js"></script> <p><i>Скрипт и стили будут подгружены только для IE6.</i></p> <![endif]--> <!--[if lte IE 7]> <p><i>Этот текст увидят только пользователи IE7, IE6 или IE5.</i></p> <![endif]--> <!--[if gt IE 9]> <p><i>Этот текст увидят только пользователи IE10 и более поздних версий.</i></p> <![endif]--> <!--[if ! IE 6]><!--> <p><i>Этот текст увидят все, кроме несчастных обладателей IE6.</i></p> <!--<![endif]-->
Вот результат работы такого кода:
Этот текст увидят все, кроме несчастных обладателей IE6.
Как видно по примерам, в условных комментариях можна пользоваться «операторами» и составлять с помощью них выражения, которые проверяют определенные утверждения про браузер. В частности, доступны операторы lt («less then» — меньше чем), lte («less then or equal to» — меньше чем или равно), gt («greater then» — больше чем), lte («greater then or equal to» — больше чем или равно) и оператор отрицания «!».
Обратите внимание, что последний пример отличается от всех остальных — его текст содержится не внутри комментария, а между двумя отдельными комментариями. Иначе браузеры, не знающие про условные комментарии IE (то есть все, кроме IE), просто проигнорировали бы его. Синтаксис в последнем примере несколько запутан. Это необходимость: только так весь этот блок есть корректным («валидным») HTML-кодом.
Условные комментарии, в силу своей структуры, не так хрупки, как обычные CSS-хаки, поэтому вполне могут использоваться (и очень часто используются) на практике.
Статьи о веб-программировании:
Различение браузеров



