web-dev-qa-db-fra.com

Est-il possible de définir l'ordre d'empilement des pseudo-éléments sous leur élément parent?

J'essaie de styler un élément avec le sélecteur CSS du pseudo-élément :after

#element {
    position: relative;
    z-index: 1;
}

#element::after {
    position:relative;
    z-index: 0;
    content: " ";
    position: absolute;
    width: 100px;
    height: 100px;
}

Il semble que l'élément ::after ne puisse pas être inférieur à l'élément lui-même.

Y a-t-il moyen de faire descendre le pseudo élément plus bas que l'élément lui-même?

258
adardesign

pseudo-éléments sont traités comme des descendants de leur élément associé. Pour positionner un pseudo-élément en dessous de son parent, vous devez créer un nouveau contexte de pile pour changer l'ordre de pile par défaut.
Le positionnement du pseudo-élément (absolu) et l'attribution d'une valeur d'index z autre que "auto" créent le nouveau contexte de pile.

#element { 
    position: relative;  /* optional */
    width: 100px;
    height: 100px;
    background-color: blue;
}

#element::after {
    content: "";
    width: 150px;
    height: 150px;
    background-color: red;

    /* create a new stacking context */
    position: absolute;
    z-index: -1;  /* to be below the parent element */
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Position a pseudo-element below its parent</title>
</head>
<body>
  <div id="element">
  </div>
</body>
</html>
322
Arley

Je sais que c'est un vieux fil, mais je ressens le besoin de poster la bonne réponse. La réponse réelle à cette question est que vous devez créer un nouveau contexte d'empilement sur le parent de l'élément avec le pseudo-élément (et vous devez lui attribuer un z-index, pas seulement une position).

Comme ça:

#parent {
    position: relative;
    z-index: 1;
}
#pseudo-parent {
    position: absolute;
    /* no z-index allowed */
}
#pseudo-parent:after {
    position: absolute;
    top:0;
    z-index: -1;
}

Cela n'a rien à voir avec l'utilisation de: pseudo-éléments avant ou: après.

#parent { position: relative; z-index: 1; }
#pseudo-parent { position: absolute; } /* no z-index required */
#pseudo-parent:after { position: absolute; z-index: -1; }

/* Example styling to illustrate */
#pseudo-parent { background: #d1d1d1; }
#pseudo-parent:after { margin-left: -3px; content: "M" }
<div id="parent">
 <div id="pseudo-parent">
   &nbsp;
 </div>
</div>
236
Adam

Essaye le

el {
  transform-style: preserve-3d;
}
el:after {
  transform: translateZ(-1px);
}
43
Eugen Govorun

Deux problèmes sont en jeu ici:

  1. La spécification CSS 2.1 stipule que "les éléments de pseudo-éléments :beforeet :after interagissent avec d'autres boîtes, telles que les boîtes d'exécution, comme s'il s'agissait de véritables éléments insérés juste à l'intérieur de l'élément qui leur est associé." Compte tenu de la manière dont les index z sont mis en œuvre dans la plupart des navigateurs, il est assez difficile (lire, je ne connais aucun moyen) de déplacer un contenu plus bas que l'index z de leur élément parent dans le DOM qui fonctionne dans tous les navigateurs.

  2. Le numéro 1 ci-dessus ne signifie pas nécessairement que c'est impossible, mais le deuxième obstacle est en réalité pire: c'est finalement une question de support du navigateur. Firefox ne supportait pas du tout le positionnement du contenu généré jusqu'à FF3.6. Qui sait sur les navigateurs comme IE. Donc, même si vous pouvez trouver un hack pour le faire fonctionner dans un seul navigateur, il est très probable que cela ne fonctionnera que dans ce navigateur.

La seule chose à laquelle je peux penser que cela fonctionnera sur tous les navigateurs est d'utiliser du javascript pour insérer l'élément plutôt que du CSS. Je sais que ce n'est pas une bonne solution, mais les pseudo-sélecteurs :before et :after ne ressemblent vraiment pas du tout à ce qu'ils vont le couper ici.

15
Gabriel Hurley

En parlant de la spécification ( http://www.w3.org/TR/CSS2/zindex.html ), puisque a.someSelector est positionné, il crée un nouveau contexte d'empilement que ses enfants ne peut pas sortir de. Laissez a.someSelector unpositioned, puis l'enfant a.someSelector:after pourra être placé dans le même contexte que a.someSelector.

11
cweider

Je sais que cette question est ancienne et a une réponse acceptée, mais j'ai trouvé une meilleure solution au problème. Je la poste ici pour ne pas créer une question en double et la solution est toujours disponible pour les autres.

Changer l'ordre des éléments. Utilisez le pseudo-élément :before pour le contenu devant être placé en dessous, puis ajustez les marges pour compenser. Le nettoyage de la marge peut être compliqué, mais le z-index souhaité sera conservé.

J'ai testé cela avec IE8 et FF3.6 avec succès.

9
D.N.

Définissez le z-index du :before ou :after pseudo-élément sur -1 et donnez-lui une position qui honore la propriété z-index (absolute, relative ou fixed). Cela fonctionne car le z-index du pseudo-élément est relatif à son élément parent, plutôt que <html>, qui est la valeur par défaut pour les autres éléments. Ce qui a du sens car ce sont des éléments enfants de <html>.

Le problème que j’avais (c’est ce qui m’a amené à cette question et à la réponse acceptée ci-dessus) est que j’essayais d’utiliser un pseudo-élément :after pour avoir l’imagination avec un arrière-plan à un élément avec z-index sur 15. et même avec un z-index de 14, il était toujours affiché au-dessus de son parent. En effet, dans ce contexte de pile, son parent a un z-index de 0.

Espérons que cela aide à clarifier un peu ce qui se passe.

4
Noah Erickson

Je l'ai réglé très simple:

.parent {
  position: relative;
  z-index: 1;
}

.child {
  position: absolute;
  z-index: -1;
}

Cela empile le parent à z-index: 1, ce qui donne à l'espace enfant la possibilité de "finir" à z-index: 0 car d'autres éléments dom existent "sur z-index: 0. Si nous ne donnons pas le parent un z-index de 1 l'enfant se retrouvera sous les autres éléments dom et ne sera donc pas visible.

Cela fonctionne aussi pour des pseudo-éléments tels que : after

0
Wachem

Je ne sais pas si quelqu'un aura le même problème avec cela. La réponse sélectionnée est partiellement correcte.

Ce que vous devez avoir c'est:

parent{
  z-index: 1;
}
child{
 position:relative;
 backgr
0
Rodrigo García