Czy mogę mieć wiele: przed pseudoelementami dla tego samego elementu?

116

Czy można mieć wiele :beforepseudo dla tego samego elementu?

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

Próbuję zastosować powyższe style do tego samego elementu za pomocą jQuery, ale stosowany jest tylko najnowszy, nigdy oba.

ChrisOdney
źródło

Odpowiedzi:

94

W CSS2.1 element może mieć tylko jeden z dowolnego rodzaju pseudoelementu w dowolnym momencie. (Oznacza to, że element może mieć zarówno element :beforea, jak i :afterpseudoelement - po prostu nie może mieć więcej niż jednego elementu każdego rodzaju).

W rezultacie, gdy masz wiele :beforereguł pasujących do tego samego elementu, wszystkie będą kaskadowo stosowane do pojedynczego :beforepseudoelementu, tak jak w przypadku zwykłego elementu. W Twoim przykładzie wynik końcowy wygląda następująco:

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

Jak widać, tylko contentdeklaracja, która ma najwyższy priorytet (jak wspomniano, ta, która jest ostatnia) odniesie skutek - reszta deklaracji zostanie odrzucona, tak jak w przypadku każdej innej właściwości CSS.

To zachowanie jest opisane w sekcji Selektory w CSS2.1 :

Pseudoelementy zachowują się jak prawdziwe elementy w CSS z wyjątkami opisanymi poniżej i gdzie indziej.

Oznacza to, że selektory z pseudoelementami działają tak samo, jak selektory normalnych elementów. Oznacza to również, że kaskada powinna działać w ten sam sposób. O dziwo, CSS2.1 wydaje się być jedynym odniesieniem; ani css3-selectors, ani css3-cascade w ogóle o tym nie wspominają i okaże się, czy zostanie to wyjaśnione w przyszłej specyfikacji.

Jeśli element może dopasować więcej niż jeden selektor do tego samego pseudoelementu i chcesz, aby wszystkie z nich w jakiś sposób zostały zastosowane, będziesz musiał utworzyć dodatkowe reguły CSS z połączonymi selektorami, abyś mógł dokładnie określić, co przeglądarka powinna w nich robić przypadkach. Nie mogę podać pełnego przykładu zawierającego contentwłaściwość tutaj, ponieważ nie jest na przykład jasne, czy symbol lub tekst powinien być na pierwszym miejscu. Ale selektor, którego potrzebujesz dla tej połączonej reguły, to albo .circle.now:beforealbo .now.circle:before- niezależnie od tego, który selektor wybierzesz, jest preferencją osobistą, ponieważ oba selektory są równoważne, jest to tylko wartośćcontent właściwości będziesz potrzebować samodzielnie zdefiniować.

Jeśli nadal potrzebujesz konkretnego przykładu, zobacz moją odpowiedź na to podobne pytanie .

Starsza specyfikacja treści css3 zawiera sekcję dotyczącą wstawiania wielu ::beforei ::afterpseudoelementów przy użyciu notacji zgodnej z kaskadą CSS2.1, ale należy pamiętać, że ten konkretny dokument jest przestarzały - nie był aktualizowany od 2003 r. I nikt nie wdrożyła tę funkcję w ciągu ostatniej dekady. Dobra wiadomość jest taka, że ​​porzucony dokument jest aktywnie przepisywany pod postacią css-content-3 i css-pseudo-4 . Zła wiadomość jest taka, że ​​cecha wielu pseudoelementów nigdzie nie występuje w żadnej ze specyfikacji, prawdopodobnie z powodu braku zainteresowania implementującego.

BoltClock
źródło
12
W danym przypadku, jeśli element należy zarówno circledo klasy now, jak i do klasy , obie reguły mają zastosowanie do :beforepseudoelementu elementu, ale normalny CSS implikuje, że tylko jedno z contentustawień może obowiązywać (zgodnie z normalnymi regułami kaskadowymi). Chodzi o to, że contentsię nie kumuluje.
Jukka K. Korpela
Okazuje się, że to pytanie, na które odpowiedziałem kilka miesięcy później, jest duplikatem tego. Od tego czasu połączyłem większość informacji z drugiej odpowiedzi, która zasadniczo rozszerza wszystko, co powiedział @Jukka powyżej, w tę, ponieważ uzyskuje znacznie większy ruch, oprócz tego, że pojawia się jako pierwszy.
BoltClock
1
Po 13 latach wersja robocza css-content-3 została ostatecznie zaktualizowana . Sekcja pseudoelementów została definitywnie usunięta na korzyść css-pseudo-4, która nie zezwala na wiele ::beforeani ::afterpseudo-elementów.
Oriol
@Oriol: właściwie 12 lat. FPWD css-pseudo-4 został wprowadzony w zeszłym roku, w którym to czasie css-content-3 został już zaktualizowany, aby wskazywał na nową specyfikację.
BoltClock
@BoltClock Wersja robocza edytora css-content-3 na drafts.csswg.org została zaktualizowana jakiś czas temu, ale wersja robocza na w3.org była jeszcze do niedawna wersją z 2003 roku. Wciąż miałem pewne nadzieje ...
Oriol
31

Jeśli twój główny element ma jakieś elementy potomne lub tekst, możesz to wykorzystać.

Ustaw swój główny element względny (lub bezwzględny / ustalony) i użyj obu: przed i: po pozycjonowanym absolutnym (w mojej sytuacji musiał to być absolutny, nie wiem o twoim).

Teraz, jeśli chcesz jeszcze jednego pseudoelementu, dołącz absolut: przed jednym z dzieci elementu głównego (jeśli masz tylko tekst, umieść go w rozpiętości, teraz masz element), który nie jest względny / absolutny / ustalony .

Ten element zacznie zachowywać się tak, jakby jego właściciel był Twoim głównym elementem.

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
źródło
2
Chociaż wybrana odpowiedź jest dokładna, w moim przypadku było to możliwe obejście. Udało mi się zasymulować posiadanie wielu pseudo elementów bez konieczności dodawania kolejnych węzłów do DOM!
matt.kauffman23
@ matt.kauffman23 więc, czy mógłbyś powiedzieć, jak przeprowadziłeś symulację?
BbIKTOP,
1
@BbIKTOP przepraszam, właśnie zobaczyłem twój komentarz. W moim przypadku pracowałem nad modalem, który zawsze miał dzieci, więc skończyło się na czymś takim:.modal:first-child:before { …
matt.kauffman 23
@ matt.kauffman23 Aby przypomnieć sobie taki szczegół po ponad 6 latach, masz świetną pamięć!
ChrisOdney
1

Rozwiązałem to za pomocą:

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

Używając rodziny czcionek „font awesome 5 free” dla ikony, a następnie musimy ponownie określić czcionkę, której używamy, ponieważ jeśli tego nie zrobimy, nawigator użyje domyślnej czcionki (razy new roman lub coś podobnego to).

Keko Perera
źródło