Le merdier du “stacking context” en CSS (aka “pourquoi mon z-index marche pas bordel de merde” ?)


C’est une règle en CSS que beaucoup de designers connaissent, mais la première fois qu’on s’y frotte on se sent très con: on ne peut pas appliquer z-index à un élément dont le parent possède déjà un “stacking context”.

Ce n’est pas un bug, c’est comme ça que c’est supposé fonctionner.

Qu’est-ce qu’un “stacking context” ?

On appelle “stacking context” l’état d’un élément que le navigateur garde en mémoire pour effectuer le rendu de cet élément dans la page. Le “stacking context” dit si l’élément doit être devant ou derrière chaque autre élément se superposant à l’écran avec lui.

Chaque fois que vous utilisez une propriété comme z-index, opacity ou transform sur un élément dans un fichier CSS, le navigateur recalcule le “stacking context” pour savoir si il met maintenant cet élément devant ou derrière les autres à la même position que lui.

Et du coup, j’ai pas compris le début, c’est quoi déjà le problème ?

Si vous faites un truc qui change le “stacking context” d’un élément, vous ne pouvez appliquer z-index sur aucun de ses enfants.

Ainsi si vous avez un HTML comme ça:

<p class="parent">
    <span class="child">Truc</span>
</p>

Et que vous faites ça dans votre CSS:

.parent {
    z-index: 1;
    opacity: 0.5;
    transform: rotate(5deg);
}
 
.child {
    z-index: -1;
}

La dernière règle n’aura aucun effet.

Donc si vous vous acharnez sur F5 parce qu’un z-index semble ne pas marcher quelque part, vous savez maintenant qu’il faut juste remonter la chaîne de tous les parents de cet élément pour voir si vous avez pas à un moment changé le “stacking context” de l’un d’entre eux.

12 thoughts on “Le merdier du “stacking context” en CSS (aka “pourquoi mon z-index marche pas bordel de merde” ?)

  • anon

    Moi je préfère le viol de toutes conventions établies a coup de “!important”

    Si toutes mes règles sont importantes, je me sens important.
    Vive le CSS

  • MatTheCat

    Dans l’exemple la règle n’aura aucun effet parce que z-index n’agit que sur les éléments positionnés (dont la propriété position vaut autre chose que static).
    Et sur un élément positionné, z-index est relatif à la pile établie par le premier parent positionné : http://www.w3.org/TR/CSS2/visuren.html#z-index

    Donc si, z-index a un effet même sur un élément dont le parent a aussi un z-index.

  • MatTheCat

    Ah en fait ce que vous voulez mettre en avant c’est le fait que z-index n’a d’effet sur l’élément que dans la pile à laquelle il appartient (sauf exception !) ?
    Honnêtement je n’ai pas compris ça en lisant l’article =/

  • Sam Post author

    Ouai, on sent que mon expertise est bien moindre en front end, mes articles sont beaucoup plus approximatif. Bah, c’est pas grâve, y toujours quelqu’un pour donner tous les détails en comment.

  • le hollandais volant

    @MatTheCat +0.5

    Si ton .child est en position:relative (ou absolute, fixed), alors ça marche (suffit de tester avec des background semi-transparents).

    Donc si, z-index a un effet même sur un élément dont le parent a aussi un z-index.

    Tout dépend : si .child et .parent ont chacun des position:relative, alors là le .child ne pourra pas se placer sous le .parent.

    Donc en gros, si le .parent a un position:relative, alors le z-index du .child n’a d’effets que sur les autres .child (donc les éléments frères et sœurs, si vous voulez).

    z-index n’a d’effet sur l’élément que dans la pile à laquelle il appartient

    C’est bien ça, si la pile possède un position différent de static.

  • Sam Post author

    Merci pour ces compléments d’information à tous les deux. C’est très utile.

  • mak mohamed

    j’ais un probleme a “menu” il se desparetre avent que je pass au lien suivent pouver vous m’ide slvp

    HTML:

    <

    div id=”menu”>

    accueil

    …….FELIER……….

    Infirmier polyvalent
    ortho
    sage femme
    assestant sociale

    Lien menu 3

    lien sous menu 3
    lien sous menu 3
    lien sous menu 3
    lien sous menu 3

    Lien menu 4

    Lien sous menu 4
    Lien sous menu 4
    Lien sous menu 4
    Lien sous menu 4

    css: #menu {

    border-radius: 5px 5px 0 0;
    bottom: 0px;
    position:absolute ;
    width: 90%;
    }

    #menu-demo2,#menu-demo2 ul{

    padding:0;

    margin:0px;

    list-style:none;

    text-align:center;

    }

    #menu-demo2 li{

    display:inline-block;

    position:relative;

    border-radius:8px 8px 0 0;

    }

    #menu-demo2 ul li{

    display:inherit;

    border-radius:5px;

    }

    #menu-demo2 ul li:hover{
    border-radius:0;

    }
    #menu-demo2 ul li:last-child{
    border-radius:0 0 8px 8px;
    }
    #menu-demo2 ul{
    position:absolute;
    max-height:0;
    left: 0;
    right: 0;
    overflow:hidden;
    -moz-transition: .3s all .3s;
    -webkit-transition: .3s all .3s;
    transition: .3s all .3s;
    }
    #menu-demo2 li:hover ul{
    max-height:15em;
    }
    /* background des liens menus */
    #menu-demo2 li:first-child{
    background-color: #65537A;
    background-image:-webkit-linear-gradient(top, #65537A 0%, #2A2333 100%);
    background-image:linear-gradient(to bottom, #65537A 0%, #2A2333 100%);
    }
    #menu-demo2 li:nth-child(2){
    background-color: #729EBF;
    background-image: -webkit-linear-gradient(top, #729EBF 0%, #333A40 100%);
    background-image:linear-gradient(to bottom, #729EBF 0%, #333A40 100%);
    }
    #menu-demo2 li:nth-child(3){
    background-color: #F6AD1A;
    background-image:-webkit-linear-gradient(top, #F6AD1A 0%, #9F391A 100%);
    background-image:linear-gradient(to bottom, #F6AD1A 0%, #9F391A 100%);
    }
    #menu-demo2 li:last-child{
    background-color: #CFFF6A;
    background-image:-webkit-linear-gradient(top, #CFFF6A 0%, #677F35 100%);
    background-image:linear-gradient(to bottom, #CFFF6A 0%, #677F35 100%);
    }
    /* background des liens sous menus */
    #menu-demo2 li:first-child li{
    background:#2A2333;
    }
    #menu-demo2 li:nth-child(2) li{
    background:#333A40;
    }
    #menu-demo2 li:nth-child(3) li{
    background:#9F391A;
    }
    #menu-demo2 li:last-child li{
    background:#677F35;
    }
    /* background des liens menus et sous menus au survol */
    #menu-demo2 li:first-child:hover, #menu-demo2 li:first-child li:hover{
    background:#65537A;
    }
    #menu-demo2 li:nth-child(2):hover, #menu-demo2 li:nth-child(2) li:hover{
    background:#729EBF;
    }
    #menu-demo2 li:nth-child(3):hover, #menu-demo2 li:nth-child(3) li:hover{
    background:#F6AD1A;
    }
    #menu-demo2 li:last-child:hover, #menu-demo2 li:last-child li:hover{
    background:#CFFF6A;
    }
    /* les a href style d'ecriture*/
    #menu-demo2 a{
    text-decoration:none;
    display:block;
    padding:8px 32px;
    color:#fff;
    font-family:arial;
    }
    #menu-demo2 ul a{
    padding:8px 0;
    }
    #menu-demo2 li:hover li a{
    z-index:0;
    color:#fff;
    text-transform:inherit;
    }
    #menu-demo2 li:hover a, #menu-demo2 li li:hover a{
    color:#000;

    }

    • Sam Post author

      Ceci est un blog sur Python, pas un forum d’aide au HTML.

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.