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

Автор: Евгений Рыжков и Татьяна Головко Дата публикации: 12.03.2011
Последнее обновление:12.09.2017

Все браузеры имеют свой список поддерживаемых HTML элементов. Например, Mozilla Firefox хранит этот список в nsElementTable.cpp. Те элементы, которые в этом списке отсутствуют, воспринимаются как «неизвестные элементы». Есть два фундаментальных вопроса касательно неизвестных элементов:

Как должен быть оформлен элемент?

По умолчанию тег <p> имеет отступы сверху и снизу, <blockquote> имеет отступ слева, <h1> выводится более крупным шрифтом.

Как выглядит элемент в DOM?

Мозиловский nsElementTable.cpp включает в себя информацию, какие теги может содержать тот или иной элемент. Например, вот такой невалидный код <p><p> будет воспринят не как один абзац, вложенный в другой, а как два сестринских абзаца: второй отрывающийся тег <p> автоматически закрывает перед ним стоящий. Но если написать <p><span>, тогда абзац не закроется и в DOM <span> будет дочерним элементом по отношению к <p>, т.к. <p> — это блочный элемент, который может содержать строчные, а <span> и является таковым.

Разные браузеры на эти вопросы отвечают по разному. Основной проблемой являются различия между основными браузерами и Microsoft Internet Explorer.

На первый вопрос, кажется, есть достаточно простой ответ: все неизвестные элементы не имеют каких-либо специальных стилей по умолчанию и просто наследуют их от родителей. И, если нужно, пусть автор сам задает им нужные стили. К сожалению, IE (до версии 9) не позволяет задавать стили неизвестным элементам. Например, есть такая разметка:

<style type="text/css">
article { display: block; border: 1px solid red }
</style>
…
<article>
	<h1>Welcome to Initech</h1>
	<p>This is your <span>first day</span>.</p>
</article>

IE до 8-й версии включительно не отобразит красную границу вокруг article. Разработчики IE уверяют, что в 9-й версии такой проблемы не будет.

Вторая проблема заключается в том, что браузеры не знают, что создавать в DOM, когда встречается неизвестный элемент. И снова наибольшие проблемы с IE. Если этому браузеру встретится неизвестный элемент, он создаст пустой DOM элемент, который не будет иметь дочерних элементов. Все элементы, которые должны были быть для него дочерними, будут вставлены как сестринские.

Чтобы была понятна разница, рассмотрим дерево элементов. Как описывает DOM HTML5:

article
|
+--h1 (потомок для article)
|  |
|  +--text node "Welcome to Initech"
|
+--p (потомок для article, сестринский для h1)
   |
   +--text node "This is your "
   |
   +--span
   |  |
   |  +--text node "first day"
   |
   +--text node "."

А вот как дерево строит Internet Explorer:

article (без потомков)
h1 (сестринский для article)
|
+--text node "Welcome to Initech"
p (сестринский для h1)
|
+--text node "This is your "
|
+--span
|  |
|  +--text node "first day"
|
+--text node "."

К счастью существует чудесный способ решения этой проблемы. Если создать фиктивный элемент с помощью Javascript до того, как этот элемент будет использован на странице, IE волшебным образом начинает признавать элемент <article> и даже позволит применять к нему CSS-стили. Не нужно перед каждой вставкой неизвестного для IE тега создавать фиктивный элемент. Достаточно это сделать один раз, чтобы этот элемент признавался по всей странице. Например:

<html>
	<head>
		<style>
		article { display: block; border: 1px solid red }
		</style>
		<script>document.createElement("article");</script>
	</head>
	<body>
		<article>
			<h1>Welcome to Initech</h1>
			<p>This is your <span>first day</span>.</p>
		</article>
	</body>
</html>

Такое волшебство работает во всех версиях IE, и даже в IE6. Этот прием можно расширить — создать фиктивные копии сразу всех новых HTML5 элементов. Их никто не увидит, они не попадут в DOM, они просто помогут рассказать старым браузерам о новых HTML5 тегах.

Реми Шарп (Remy Sharp) создал простой скрипт, и назвал его «Включение HTML5 элементов». Скрипт уже претерпел несколько изменений и возможно продолжает меняться, но вот его основная суть:

<!--[if lt IE 9]>
<script>
var e = ("abbr,article,aside,audio,canvas,datalist,details," +
"figure,footer,header,hgroup,mark,menu,meter,nav,output," +
"progress,section,time,video").split(',');
for (var i = 0; i < e.length; i++) {
document.createElement(e[i]);
}
</script>
<![endif]-->

Тут используются условные комментарии. IE интерпретирует этот блок так: «если версия браузера меньше 9-й, тогда выполняем данный блок». Любой другой браузер будет этот кусок кода воспринимать как обычный HTML комментарий. Т.е. Interner Explorer (вплоть до 8-й версии) будет выполнять данный код, а другие браузеры его полностью игнорировать. Условные комментарии дают возможность быстрее загружаться страницам в браузерах, поддерживающих HTML5.

Код скрипта весьма прост. Переменная e представляет собой массив строк, который содержит перечень новых тегов. В цикле, из каждого элемента массива по его значению создается фиктивный элемент с помощью document.createElement(). Так как мы игнорируем возвращаемое этой функцией значение, в DOM не вставляются созданные элементы. Но этого и не нужно, ведь IE уже начинает воспринимать новые теги.

Реми Шарп сжала скрипт и выложила на Google Project Hosting. Поэтому, можно в своих проектах подключать внешний скрипт:

<head>
<meta charset="utf-8" />
<title>My Weblog</title>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>

Вот теперь мы готовы использовать новые HTML5 теги.

Куда дальше