Puis-je avoir plusieurs pseudo-éléments: avant pour le même élément?

116

Est-il possible d'avoir plusieurs :beforepseudos pour le même élément?

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

J'essaie d'appliquer les styles ci-dessus au même élément en utilisant jQuery, mais seul le plus récent est appliqué, jamais les deux.

ChrisOdney
la source

Réponses:

94

Dans CSS2.1, un élément ne peut avoir au plus qu'un pseudo-élément quelconque à tout moment. (Cela signifie qu'un élément peut avoir à la fois un :beforeet un :afterpseudo-élément - il ne peut tout simplement pas en avoir plus d'un de chaque type.)

En conséquence, lorsque vous avez plusieurs :beforerègles correspondant au même élément, elles seront toutes en cascade et s'appliqueront à un seul :beforepseudo-élément, comme avec un élément normal. Dans votre exemple, le résultat final ressemble à ceci:

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

Comme vous pouvez le voir, seule la contentdéclaration qui a la priorité la plus élevée (comme mentionné, celle qui vient en dernier) prendra effet - le reste des déclarations est ignoré, comme c'est le cas avec toute autre propriété CSS.

Ce comportement est décrit dans la section Sélecteurs de CSS2.1 :

Les pseudo-éléments se comportent comme de vrais éléments en CSS avec les exceptions décrites ci-dessous et ailleurs.

Cela implique que les sélecteurs avec pseudo-éléments fonctionnent exactement comme les sélecteurs pour les éléments normaux. Cela signifie également que la cascade doit fonctionner de la même manière. Étrangement, CSS2.1 semble être la seule référence; ni css3-selectors ni css3-cascade ne le mentionnent du tout, et il reste à voir si cela sera clarifié dans une spécification future.

Si un élément peut correspondre à plus d'un sélecteur avec le même pseudo-élément et que vous souhaitez que tous s'appliquent d'une manière ou d'une autre, vous devrez créer des règles CSS supplémentaires avec des sélecteurs combinés afin de pouvoir spécifier exactement ce que le navigateur doit faire dans ces cas. Je ne peux pas fournir un exemple complet incluant la contentpropriété ici, car il n'est pas clair, par exemple, si le symbole ou le texte doit venir en premier. Mais le sélecteur dont vous avez besoin pour cette règle combinée est soit .circle.now:beforeou .now.circle:before- quel que soit le sélecteur que vous choisissez est votre préférence personnelle car les deux sélecteurs sont équivalents, c'est uniquement la valeur de la contentpropriété que vous devrez définir vous-même.

Si vous avez encore besoin d'un exemple concret, voyez ma réponse à cette question similaire .

La spécification de contenu css3 héritée contient une section sur l'insertion de plusieurs ::beforeet ::afterpseudo-éléments en utilisant une notation compatible avec la cascade CSS2.1, mais notez que ce document particulier est obsolète - il n'a pas été mis à jour depuis 2003, et personne ne l'a mis en œuvre cette fonctionnalité au cours de la dernière décennie. La bonne nouvelle est que le document abandonné subit activement une réécriture sous le couvert de css-content-3 et css-pseudo-4 . La mauvaise nouvelle est que la fonctionnalité de pseudo-éléments multiples ne se trouve nulle part dans l'une ou l'autre spécification, probablement en raison, encore une fois, du manque d'intérêt de l'implémenteur.

BoltClock
la source
12
Dans le cas donné, si un élément appartient à la fois à la classe circleet à la classe now, les deux règles s'appliquent au :beforepseudo-élément de l'élément, mais le CSS normal implique qu'un seul des contentparamètres peut prendre effet (par des règles de cascade normales). Le fait est que contentcela ne s'accumule pas.
Jukka K. Korpela
Il s'avère que cette question à laquelle j'ai répondu plusieurs mois plus tard est un double de celle-ci. Depuis, j'ai fusionné la plupart des informations de l'autre réponse, qui étend fondamentalement tout ce que @Jukka a dit ci-dessus, dans celle-ci, car il génère beaucoup plus de trafic, en plus d'être le premier.
BoltClock
1
Après 13 ans, le brouillon css-content-3 a enfin été mis à jour . La section pseudo-éléments a définitivement été supprimée au profit de css-pseudo-4, qui n'autorise pas les multiples ::beforeni les ::afterpseudo-éléments.
Oriol
@Oriol: 12 ans, en fait. le FPWD de css-pseudo-4 a été introduit l'année dernière, date à laquelle css-content-3 avait déjà été mis à jour pour pointer vers la nouvelle spécification.
BoltClock
@BoltClock Le brouillon de l'éditeur css-content-3 sur drafts.csswg.org a été mis à jour il y a quelque temps, mais le brouillon de travail sur w3.org était encore celui de 2003 jusqu'à récemment. J'avais encore des espoirs ...
Oriol
31

Si votre élément principal a des éléments enfants ou du texte, vous pouvez l'utiliser.

Positionnez votre élément principal relatif (ou absolu / fixe) et utilisez les deux: avant et: après positionné absolu (dans ma situation, il devait être absolu, je ne sais pas pour le vôtre).

Maintenant, si vous voulez un pseudo-élément de plus, attachez un absolu: before à l'un des enfants de l'élément principal (si vous n'avez que du texte, mettez-le dans une étendue, maintenant vous avez un élément), qui n'est pas relatif / absolu / fixe .

Cet élément commencera à agir comme son propriétaire est votre élément principal.

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
la source
2
Bien que la réponse choisie soit exacte, c'était une solution viable pour mon cas. J'ai pu simuler plusieurs éléments psuedo sans avoir besoin d'ajouter plus de nœuds au DOM!
matt.kauffman23
@ matt.kauffman23 alors, pourriez-vous s'il vous plaît dire comment avez-vous simulé?
BbIKTOP
1
@BbIKTOP désolé vient de voir votre commentaire. Dans mon cas, je travaillais sur un modal qui avait toujours des enfants, alors je me suis retrouvé avec quelque chose comme:.modal:first-child:before { …
matt.kauffman23
@ matt.kauffman23 Pour vous rappeler un détail comme celui-ci après plus de 6 ans, vous avez un super souvenir!
ChrisOdney
1

J'ai résolu ce problème en utilisant:

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

En utilisant la famille de polices "font awesome 5 free" pour l'icône, et après, nous devons spécifier la police que nous utilisons à nouveau car si nous ne le faisons pas, le navigateur utilisera la police par défaut (fois new roman ou quelque chose comme ce).

Keko Perera
la source