Могу ли я иметь несколько псевдоэлементов: before для одного и того же элемента?

116

Возможно ли иметь несколько :beforeпсевдонимов для одного и того же элемента?

.circle:before {
    content: "\25CF";
    font-size: 19px;
}
.now:before{
    content: "Now";
    font-size: 19px;
    color: black;
}

Я пытаюсь применить указанные выше стили к одному и тому же элементу с помощью jQuery, но применяется только последний из них, а не оба сразу.

ChrisOdney
источник

Ответы:

94

В CSS2.1 элемент может иметь не более одного псевдоэлемента любого типа в любое время. (Это означает, что элемент может иметь как a, так :beforeи :afterпсевдоэлемент - просто он не может иметь более одного элемента каждого типа.)

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

.circle.now:before {
    content: "Now";
    font-size: 19px;
    color: black;
}

Как видите, contentвступит в силу только объявление с наивысшим приоритетом (как уже упоминалось, последнее) - остальные объявления отбрасываются, как и в случае с любым другим свойством CSS.

Это поведение описано в разделе « Селекторы» CSS2.1 :

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

Это означает, что селекторы с псевдоэлементами работают так же, как селекторы для обычных элементов. Это также означает, что каскад должен работать точно так же. Странно, но CSS2.1 кажется единственным справочником; ни css3-selectors, ни css3-cascade вообще не упоминают об этом, и еще неизвестно, будет ли это разъяснено в будущей спецификации.

Если элемент может соответствовать нескольким селекторам с одним и тем же псевдоэлементом, и вы хотите, чтобы все они каким-то образом применялись, вам нужно будет создать дополнительные правила CSS с комбинированными селекторами, чтобы вы могли точно указать, что браузер должен делать в этих случаи. Я не могу привести здесь полный пример, включая это contentсвойство, поскольку неясно, например, должен ли быть первым символ или текст. Но для этого комбинированного правила вам нужен селектор .circle.now:beforeили .now.circle:before- какой бы селектор вы ни выбрали, это личное предпочтение, поскольку оба селектора эквивалентны, это только значение contentсвойства, которое вам нужно будет определить самостоятельно.

Если вам все еще нужен конкретный пример, посмотрите мой ответ на этот аналогичный вопрос .

Спецификация наследия CSS3-контент содержит раздел о вставке несколько ::beforeи ::afterпсевдо-элементов с использованием обозначений , которая совместима с CSS2.1 каскадом, но обратите внимание , что этот конкретный документ устарел - он не обновлялись с 2003 года, и никто не имеет реализовали эту функцию в последнее десятилетие. Хорошая новость в том, что заброшенный документ активно переписывается под видом css-content-3 и css-pseudo-4 . Плохая новость заключается в том, что функция множественных псевдоэлементов нигде не встречается ни в одной из спецификаций, вероятно, опять же из-за отсутствия интереса со стороны разработчиков.

BoltClock
источник
12
В данном случае, если элемент принадлежит и классу, circleи классу now, оба правила применяются к :beforeпсевдоэлементу элемента, но нормальный CSS подразумевает, что только одна из contentнастроек может вступить в силу (по обычным каскадным правилам). Дело в том, что contentне накапливается.
Юкка К. Корпела
Оказывается, этот вопрос, на который я ответил несколько месяцев спустя, является дубликатом этого. С тех пор я объединил большую часть информации из другого ответа, который в основном расширяет все, что @Jukka сказал выше, в этот, поскольку он получает гораздо больше трафика, помимо того, что он приходит первым.
BoltClock
1
Спустя 13 лет черновик css-content-3 был наконец обновлен . Раздел псевдоэлементов определенно был удален в пользу css-pseudo-4, который не допускает множественных ::beforeили ::afterпсевдоэлементов.
Oriol
@Oriol: На самом деле, 12 лет. FPWD css-pseudo-4 был представлен в прошлом году, тогда как css-content-3 уже был обновлен, чтобы указывать на новую спецификацию.
BoltClock
@BoltClock Черновик редактора css-content-3 на drafts.csswg.org был обновлен некоторое время назад, но рабочий черновик на w3.org до недавнего времени оставался от 2003 года. У меня все еще были некоторые надежды ...
Ориол
31

Если у вашего основного элемента есть дочерние элементы или текст, вы можете его использовать.

Разместите свой основной элемент относительным (или абсолютным / фиксированным) и используйте оба: до и: после позиционирования абсолютного (в моей ситуации он должен был быть абсолютным, не знаю о вашем).

Теперь, если вам нужен еще один псевдоэлемент, прикрепите absolute: before к одному из дочерних элементов основного элемента (если у вас есть только текст, поместите его в диапазон, теперь у вас есть элемент), который не является относительным / абсолютным / фиксированным .

Этот элемент начнет вести себя так, как будто его владелец - ваш главный элемент.

HTML

<div class="circle">
    <span>Some text</span>
</div>

CSS

.circle {
    position: relative; /* or absolute/fixed */
}

.circle:before {
    position: absolute;
    content: "";
    /* more styles: width, height, etc */
}

.circle:after {
    position: absolute;
    content: "";
    /* more styles: width, height, etc */
}

.circle span {
    /* not relative/absolute/fixed */
}

.circle span:before {
    position: absolute;
    content: "";
    /* more styles: width, height, etc */
}
HydraOrc
источник
2
Хотя выбранный ответ является точным, в моем случае это было жизнеспособным решением. Я смог смоделировать наличие нескольких псевдоэлементов без необходимости добавлять дополнительные узлы в DOM!
matt.kauffman23
@ matt.kauffman23 Итак, расскажите, пожалуйста, как вы моделировали?
BbIKTOP
1
@BbIKTOP извините, только что увидел ваш комментарий. В моем случае я работал над модальным .modal:first-child:before { …
окном, в
@ matt.kauffman23 Чтобы вспоминать такую ​​деталь спустя более 6 лет, у вас отличная память!
ChrisOdney
1

Я решил это, используя:

.element:before {
    font-family: "Font Awesome 5 Free" , "CircularStd";
    content: "\f017" " Date";
}

Используя семейство шрифтов «font awesome 5 free» для значка, и после этого мы должны указать шрифт, который мы используем снова, потому что, если мы этого не сделаем, навигатор будет использовать шрифт по умолчанию (раз новый римский или что-то вроде этот).

Кеко Перера
источник