Современная верстка, Псевдоэлементы :before и :after

Веб-разработка /
Эта статья у меня лежала в черновиках очень давно, никак не мог ее дооформить, вообще задумывалась как одна из цикла статей про верстку.
Материал больше для начинающих.

Что такое псевдоэлемент и что он делает?

Собственно говоря из название можно понять что такое псевдоэлемент, это ненастоящий элемент который позволяет вставить новое содержимое «до» :before или «после» :after выбранного элемента. Псевдоэлементы ничего не изменяют в документе, они не существуют в дереве элементов документа, но видимы для пользователя и к ним можно применить стили.

Синтаксис

Применяются для вставки содержимого «до» или «после» выбранного элемента. Применение без свойства content бесполезно, вы не сможете работать с псевдоэлементами без свойства content в котором находится содержимое для вставки. Псевдоэлементы строчные элементы и относятся к текстовому уровню семантики.

li:before {
    content: "–";
}

li:after {
    content: "…";
}




В этом примере мы добавляем перед элементом символ «–», а после «…»

Можно оставить свойство content пустым(но не удалить совсем) и работать с псевдоэлементом как с обычным блоком, например:

.block {
    width: 100px;
    height: 100px;
    background-color: #000;
}
.block:before {
    content: "";
    width: 50px;
    height: 50px;
    display: block;
    background-color: #666;
}




В начале статьи, я писал «до» и «после» в кавычках, потому-что несмотря на названия, псевдоэлементы :before и :after вставляются не перед элементом и не после него, а перед контентом внутри этого элемента или после него. Повторюсь, псевдоэлементов нет в дереве элементов документа, в следствии этого прямой доступ из скриптов к ним невозможен. В CSS3 псевдоэлементы можно писать с двумя двоеточиями:

li::before {
    content: "";
}
li::after {
    content: "";
}


Это сделано для того чтобы различать псевдоэлементы и псевдоклассы. Но учтите что IE не понимает такой записи.

Вставка нетекстового содержимого

Можно вставить изображение:

p:before {
    content: url(image.jpg);
}


Заметьте что нет кавычек, если бы мы обернули ссылку кавычками то вставился бы просто текст url(image.jpg) вместо изображения.

Так же вы можете использовать attr() которая возвращает значение атрибута выбранного селектора. Например:

a:after {
    content: attr(href);
}


В этом примере после каждого элемента <a> будет выведена ссылка взятая из атрибута href элемента <a>, это можно использовать в стилях для печати.

Можно взять любой другой атрибут, но учтите что псевдоэлементы :before и :after не добавляются к пустым элементам, например к элементу который не имеет дочерних элементов и является пустым.

Здесь нужно упомянуть о доступе к псевдоэлементам из скриптов, если использовать data-* атрибуты, то можно получить доступ к контенту псевдоэлемента, например так:


<!-- HTML добавляем data-* атрибут к блоку -->
<div class="foo" data-content="some-content"></div>


/* CSS говорим content чтобы он брал текст из атрибута data-content */
.foo:before {
  content:attr(data-content);
}


//JavaScript меняем текст в атрибуте
$('.foo').attr('data-content', 'another-content')


А так же можно использовать counter(), counters() для вывода CSS счетчиков, подробнее о них в моем блоге: Автоматическая нумерация с помощью CSS счетчиков.

Спасибо udarec'у, я не написал про вставку спецсимволов. И забыл про кавычки.

Спецсимволы:

Для вставки спецсимволов используются escape-последовательности, предположим если нам нужно вставить ? или любой другой спецсимвол


p:after {
  content: "\2665";
}


Кавычки:

Кроме того есть еще свойство quotes, которое задает символы кавычек и применяется так:


Q { 
  quotes: "\201C" "\201D" "\2018" "\2019";
}
Q:before ( 
  content: open-quote;
}
Q:after ( 
  content: close-quote;
}


и у нас получится такой текст: “немного текста, и ‘еще’ текст”
т.е. указывается 2 пары кавычек, каждая пара соответствует уровню вложения кавычек.
Кроме того если мы указываем <HTML lang=«en»>, то можем сделать так:


/* Указываем пары кавычек двух уровней для двух языков, не escape-последовательности для наглядности*/
Q:lang(en) { quotes: '"' '"' "'" "'" }
Q:lang(no) { quotes: "«" "»" "<" ">" }


т.е. если кавычки будут выводится в зависимости от языка.

Псевдоэлементы :before and :after поддерживают:

  • Chrome 2+,
  • Firefox 3.5+ (У 3.0 частичная поддержка),
  • Safari 1.3+,
  • Opera 9.2+,
  • IE8+ (С небольшими ошибками),
  • Большинство мобильных браузеров.

Как же можно использовать псевдоэлементы?

Пример
Рассмотрим простенький пример с псевдоэлементами.

ul li {
    float: left;
}
li:before {
    content: "/";
    padding: 0 10px;
}




В этом примере мы добавляем слеш перед каждым элементом <li> и задаем псевдоэлементу :before поля слева и справа равными 20 пикселей. Напомню что этот код будет работать во всех браузерах кроме IE ниже 8 версии. Но как видите у первого пункта так же есть слеш. Тут нам на помощь приходит псевдокласс(не псевдоэлемент) :first-child, добавляем к коду:

li:first-child:before {
    content: none;
    padding: 0;
}




Псевдокласс :first-child применяется к первому дочернему элементу селектора, а псевдокласс :last-child применяется к последнему дочернему элементу, но так как IE понимает псевдокласс :first-child начиная с 7 версии, а псевдокласс :last-child только с 9 версии, то мы используем :first-child.

Последний штрих, делаем чтобы работало в IE7:

ul li {
    float: left;
    z-index: expression(
        runtimeStyle.zIndex = 1,
        insertAdjacentHTML('afterBegin','<span class="before">/</span>')
    );
}
li:before, li span {
    content: "/";
    padding: 0 10px;
}
li:first-child:before, li:first-child span {
    content: none;
    padding: 0;
    display: none;
}


Тут мы с помощью специального для IE фильтра к каждому элементу <li> добавляем элемент <span> со слешем и добавляем селектор li span и li:first-child span к существующим правилам, только к li:first-child span добавим display: none; чтобы убрать этот элемент.

Немного примеров еще тут раз, два, три

P.S. А вы используете псевдоэлементы/псевдоклассы в верстке?
P.P.S. Полезна ли для вас статья? Еще подобное читать будете? =)

14 комментариев

goldy
Пишите конечно, будет интересно почитать.
Сам обычно использую :first-child,:last-child, nth-child(4n+4) :)
roose
Ок, будем писать :)
yakooobin
О мясо, появилось на сайте.
Ништяк
roose
Почему мясо? =)
yakooobin
Мясо — это то, что можно откусить и будет насыщаемость и вкус.
А не просто водичка
talgautb
P.S. А вы используете псевдоэлементы/псевдоклассы в верстке?
да, обычно в меню
P.P.S. Полезна ли для вас статья? Еще подобное читать будете? =)
Да, конечно ;) делитесь опытом)
___
предпочитаю after, чем before; first-child, чем last-child
ну и сильно злоупотреблять ими не стоит :)
gorgtown
о.О, а вот и статейка которая выиграет на конкурсе в этом месяце)
udarec
Было бы неплохо написать, как вставлять СПЕЦИСМВОЛЫ в свойство content. Обычные коды не подходят)
roose
Да, упустил из виду, спасибо, сейчас добавлю)
roose
добавил
udarec
Теперь чудесно)
physicx
P.S. А вы используете псевдоэлементы/псевдоклассы в верстке?

По псевдоклассам
:first-child использую
:last-child нет, все еще поддерживаю ie7-8

При сбросе стандартных стилей браузеров:

blockquote, q {
        quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
        content: "";
        content: none;
}

Для обертки с плавающими элементами

 .name-class:after {
  content: "";
  display: table;
  clear: both;
}


P.P.S. Полезна ли для вас статья? Еще подобное читать будете? =)
Пост понравился, пишите еще
bsl_zcs
Мелочь: в конструкции
content: none;
padding: 0;
padding уже не нужен – при отсутствии генерируемого контента эти псевдоэлементы принципиально не отображаются, и всё остальное оформление уже не имеет значения. А с display: none; не нужно ни того, ни другого, поскольку управление отображением на эти псевдоэлементы тоже распространяется.
roose
Я видимо сперва не 0 ставил, а потом поменял не посмотрев) а display: none не для псевдоэлемента, а для span, который специально для ИЕ.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.