Xiper

Эмуляция after и before для IE 6-7

Автор: Александр Головко Дата публикации:

Задача

Научить IE6-7 генерировать контент, как при использовании псевдоэлементов after и before.

Немного истории

Псевдоэлементы after и before описаны еще в спецификации W3C Cascading Style Sheets, level 2 CSS2 Specification от 12 мая 1998 года. Но, как это часто бывает, процесс внедрения рекомендаций в жизнь растянулся на годы.

Opera заявила о поддержке CSS2 и, в часности, after и before с версии 4.0 (июнь года).

Safari (январь года) поддерживает after и before изначально, с версии 1.0.

В ноябре года состоялся релиз Firefox 1.0. Начиная с этой версии присутствует частичная поддержка before и after. К сожалению, в этих элементах не срабатывали, например, свойства position, float и list-style. Полная поддержка реализована только в версии 3.0 (июнь года).

Вышедшая в декабре года версия Chrome 1.0.154.36 (которая считается первой стабильной) тоже не вызывает в этом вопросе нареканий.

Дольше всех боролся с прогрессом Сами Знаете Какой Браузер. Даже появившийся в октябре года IE7 не утруждает себя поддержкой after и before. Сдался IE только в марте года, с выходом 8-й версии.

Таким образом, на данный момент безопасно использовать after и before как минимум для Opera, FF, Safari, Chrome, IE8. Если подобрать прием для IE6-7, то можно смело применять эти полезные псевдоэлементы!

Теория

Используя псевдоэлементы after и before можно вставлять автоматически генерируемый контент до и после элемента HTML. Что конкретно будет вставлено, задается CSS свойством content.

На практике это выглядит следующим образом. Попробуем, например, сделать FAQ используя список определений. Будем автоматически подставлять слова «Вопрос:» и «Ответ:».

<dl>
<dt>Тут будет какой-то вопрос</dt>
<dd>А тут ответ</dd>
</dl>

В CSS прописываем псевдоэлементы и отступ для красоты.

dt{
	margin-top:10px;
}
dt:before{
	content: "Вопрос: ";
}
dd:before{
	content: "Ответ: ";
}

Для большинства браузеров этого достаточно.

Решение

Для того, чтобы предыдущий пример сработал в IE6-7, будем использовать expression и свойство innerHTML.

CSS теперь будет такой:

dt{
	margin-top:10px;
	//z-index: expression(runtimeStyle.zIndex = 1, this.innerHTML = "Вопрос: " + this.innerHTML) /* хак для ие6 и 7 */
}
dd{
	//z-index: expression(runtimeStyle.zIndex = 1, this.innerHTML = "Ответ: " + this.innerHTML) /* хак для ие6 и 7 */
}
dt:before{
	content: "Вопрос: ";
}
dd:before{
	content: "Ответ: ";
}

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

Основной момент отражен в строках 03 и 07. Это оптимизированный expression, который выполнится только один раз. Свойство innerHTML позволяет получить доступ к HTML коду, который находиться между открывающим и закрывающим тегами.

Таким образом:

  • запись this.innerHTML = "Генерируемый контент" + this.innerHTML обеспечит вставку нового контента до существующего (т.е. эмуляция before);
  • запись this.innerHTML = this.innerHTML + "Генерируемый контент" обеспечит вставку нового контента после существующего (эмуляция псевдоэлемента after);
  • выражение, взятое в кавычки ("Генерируемый контент") — это значение эмулируемого CSS свойства content (то, что собственно вставляем).

Решение 2. Используем insertAdjacentHTML

Update. Предыдущий вариант в некоторых случаях вызывает сбои в работе IE6. Более устойчивым является использование метода insertAdjacentHTML. Фрагмент CSS, для IE6-7 в этом варианте будет таким:

dt{
	//z-index: expression(runtimeStyle.zIndex = 1, insertAdjacentHTML('afterBegin', 'Вопрос: ')); /* хак для ие6 и 7 */
}
dd{
	//z-index: expression(runtimeStyle.zIndex = 1, insertAdjacentHTML('afterBegin', 'Ответ: ')); /* хак для ие6 и 7 */
}

Для псевдоэлемента before используем параметр afterBegin, для after — beforeEnd.

Демо пример. Проверено в:

  • IE 6-8
  • Firefox 2-3.5
  • Opera 9.5-10
  • Safari 3

Особенности вставки спецсимволов

Популярное применение данного приема — вставка спецсимвола-маркера для списка. Тут нужно не забытвать, что в expression спецсимволы можно писать цифровым или мнемоническим кодом, а в свойстве content ставим слеш и шестнадцатеричный код. Подробнее об этом рассказывается в статье Вставка спецсимволов в генерируемый контент.

Материалы

  • Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification :: Pseudo-elements and pseudo-classes
  • MSDN :: innerHTML Property