Эмуляция 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