Fonctionnement réel de z-index

Probablement presque chacun de nous au moins une fois dans sa vie a utilisé la propriété z-index. De plus, chaque développeur est sûr de savoir comment cela fonctionne. En fait, quoi de plus simple que des opérations avec des entiers (en les comparant et en les affectant à des éléments). Mais tout est-il aussi simple qu'il y paraît à première vue?

Peut-être que les informations que je couvrirai ci-dessous sont en fait triviales. Cependant, je suis sûr que beaucoup le trouveront utile pour eux-mêmes. Ceux qui le connaissaient déjà pourront utiliser ce texte comme aide-mémoire dans les moments difficiles. Alors bienvenue au chat.

image

En fait, une personne commence généralement à essayer de trier un nouveau domaine pour elle-même dans trois cas: s'il rencontre des résultats inattendus au travail et ne comprend pas ce qui se passe; s'il faut aller au-delà et regarder le sujet sous un angle différent; et enfin, juste par intérêt sportif.

Mon cas n'appartient clairement pas à la troisième catégorie. Au début, plusieurs fois dans ma vie, je suis tombé sur le premier scénario en travaillant sur différents projets; cependant, il n'a pas bien compris le problème en raison de la paresse et du manque de documents clairs et compréhensibles avec des exemples. Et puis au début de cette année, j'ai commencé à écrire un moteur Web, ce qui m'a fait commencer à lire les normes et à voir généralement comment différentes choses non triviales fonctionnent dans les navigateurs populaires, et surtout, pourquoi elles fonctionnent de cette façon.

Commençons par un simple. Qu'est-ce que le z-index et à quoi sert-il?

Évidemment, c'est la coordonnée le long de l'axe Z, spécifiée pour un élément. L'axe Z est dirigé vers l'utilisateur. Un plus grand nombre est un élément plus proche.

image

Pourquoi les nombres z-index sont-ils entiers? Tout est simple. La plage est pratiquement illimitée en haut et en bas, nous n'avons donc pas besoin d'utiliser de valeurs fractionnaires. Puisque le moniteur réel n'a pas de troisième dimension (nous ne pouvons que la simuler), nous avons besoin d'une quantité sans dimension, dont la seule tâche est de fournir une comparaison des éléments (c'est-à-dire la commande de l'ensemble). Les entiers font un excellent travail de cette tâche, alors qu'ils sont plus visuels que les vrais.

Il semblerait que cette connaissance soit suffisante pour commencer à utiliser z-index sur les pages. Cependant, tout n'est pas si simple.

<div style="background: #b3ecf9; z-index: 1"></div> <div style="background: #b3ecb3; margin-top: -86px; margin-left: 38px; z-index: 0"></div> 

image

Quelque chose semble avoir mal tourné. Nous avons fait le premier bloc z-index plus que le second, alors pourquoi est-il affiché ci-dessous? Oui, il passe en revue le code plus tôt - mais il semblerait que cela ne devrait jouer un rôle qu'avec des valeurs d'index z égales.

À ce stade, il est temps d'ouvrir la norme CSS2.1, ou plutôt son application, concernant le traitement des contextes de superposition. Voici le lien .

À partir de ce petit texte très concis, vous pouvez immédiatement extraire de nombreuses informations importantes.

  1. superposition du contrôle z-index non pas sur des éléments individuels, mais sur des contextes de superposition (groupes d'éléments)
  2. Nous ne pouvons pas contrôler arbitrairement des éléments dans des contextes différents les uns par rapport aux autres: ici la hiérarchie fonctionne. Si nous sommes déjà dans un contexte «bas», alors nous ne pouvons pas en faire un élément au-dessus de l'élément d'un contexte «supérieur».
  3. z-index n'a aucun sens pour les éléments d'un flux normal (pour lesquels la propriété position est statique). Nous sommes tombés dans ce piège dans l'exemple ci-dessus.
  4. Pour qu'un élément définisse un nouveau contexte de superposition, il doit être positionné et un z-index doit lui être attribué.
  5. Si l'élément est positionné, mais que le z-index n'est pas défini, alors nous pouvons conditionnellement supposer qu'il est égal à zéro (pour les cas simples cela fonctionne comme ceci, nous considérerons les nuances plus tard).
  6. Et les contextes de superposition individuels sont définis par des éléments dont la valeur d'opacité est inférieure à un. Cela a été fait pour que vous puissiez facilement transférer le mélange alpha à la dernière étape du rendu pour le traitement par la carte vidéo.

Mais ce n'est pas tout. Il s'avère qu'avec des éléments sans z-index, ce n'est pas aussi simple que cela puisse paraître.

Le processus de rendu des éléments de la sous-arborescence de contexte peut être divisé en plusieurs étapes (dont les deux premières produisent directement la couleur d'arrière-plan et l'image d'arrière-plan de l'élément actuel qui définit le contexte).

Alors, considérez toute la liste.

3. Dérivation de contextes enfants avec un z-index négatif
4. Sortie des éléments de bloc enfant dans un flux normal (uniquement arrière-plans)
5. Sortie d'éléments flottants enfants
6. La sortie du contenu des éléments dans un flux normal: descendants en ligne et bloc en ligne, contenu en ligne à l'intérieur des descendants en bloc, y compris les lignes de texte *
7. La sortie des contextes enfants avec zéro et z-index automatique **
8. Dérivation de contextes enfants avec un z-index positif

* pour traverser l'arbre en profondeur d'abord
** pour les contextes avec z-index: auto, considérez tous les contextes enfants comme des descendants du contexte actuel, c'est-à-dire, «tirez-les» jusqu'au niveau actuel

Déjà pas si facile, non? Vous pouvez illustrer approximativement ce schéma avec l'image suivante:

image

Il est également possible d'ouvrir un exemple sur codepen et de jouer avec lui de vos propres mains.

Mais ce n'est pas tout. Il semblerait que l'algorithme soit déjà assez compliqué: nous devons d'abord extraire les contextes enfants à l'intérieur des pseudo-contextes (rappelez-vous la valeur auto?), Puis trier pour deux listes d'index z, en les organisant dans une série de nombres, puis parcourir les enfants: d'abord, bloquer dans un flux normal, puis flottant, puis inline et inline-block ...

Mais ici, nous attendons deux surprises. La première, avec chance, ne nous concernera pas. Cela est lié au fait que l'arrière-plan avec les cadres et le contenu des éléments de bloc sont affichés à différentes étapes - mais si notre moteur auto-créé pour chaque nœud de texte crée un élément automatiquement en ligne, alors tout ira bien, ils seront naturellement affichés plus tard.

Mais le second n'est pas si banal. Il est marqué
Pour chacun d'entre eux, traitez l'élément comme s'il avait créé un nouveau contexte d'empilement, mais tous les descendants positionnés et les descendants qui créent réellement un nouveau contexte d'empilement doivent être considérés comme faisant partie du contexte d'empilement parent, pas celui-ci.

éléments float et inline-block / inline (mais pas block!).

Qu'est-ce que cela signifie dans la pratique? Et cela signifie que nous devons les traiter de la même manière que les éléments avec z-index: auto. C'est-à-dire, tout d'abord, faire le tour de leurs sous-arbres et en retirer les contextes enfants, en les plaçant au niveau actuel. Mais pour le reste, nous devons les traiter comme des éléments qui définissent notre contexte. Cela signifie que tous les sous-arbres à l'intérieur d'eux, étirés après une analyse dans une liste linéaire, doivent rester atomiques. Ou, en d'autres termes, nous ne pouvons pas mélanger l'ordre des éléments de sorte que les descendants d'un tel élément «flottent» au-dessus de leur parent. Et si pour les contextes enfants, c'est intuitivement clair (parce que l'algorithme est récursif), alors ici ce n'est pas le cas.

Par conséquent, lors de l'écriture du code moteur, nous devons nous tromper pour que les éléments float, inline et inline-block ne révèlent pas pour l'instant leurs descendants (à l'exception des enfants avec positionnement et z-index, qui forment des contextes de superposition), puis s'exécutent pour eux toute la fonction est récursive, mais au contraire, en tenant compte du fait que les contextes enfants doivent être sautés lors d'une traversée.

Quelques exemples pour illustrer ce phénomène:

 <div style="float: left; background: #b3ecf9;"> <div style="width: 40px; height: 40px; background: #fff700; position: relative; z-index: -1; top: -20px; left: -20px;"></div> </div> 

image

Ici, l'enfant a un index z et est positionné. Il apparaît, mais s'affiche sous un carré bleu, car les éléments avec un indice z négatif sont affichés à l'étape 3 et les éléments flottants à l'étape 5.

 <div style="float: left; margin-top: -30px; background: #b3ecf9;"> <div style="width: 40px; height: 40px; background: #fff700; position: relative; z-index: 0;"></div> </div> <div style="background: #b3ecb3; margin-top: 52px; margin-left: 38px;"> <div style="width: 40px; height: 40px; background: #ff0000; position: relative; z-index: 0;"></div> </div> 

image

Dans cet exemple, le deuxième élément (vert) est affiché avant le premier (bleu), et donc en dessous. Cependant, les enfants sont tirés vers le haut (car ils définissent leurs propres contextes), dans ce cas, ils vont dans le même ordre dans lequel ils vont exactement dans l'arbre d'origine (l'ordre de leurs ancêtres après la permutation n'est pas important!). Si nous définissons le premier enfant sur un z-index égal à 1, nous obtenons l'image suivante:

image

Ajoutez plus d'éléments.

 <div style="float: left; background: #b3ecf9;"> <div style="float: left"> <div style="width: 40px; height: 40px; background: #fff700; position: relative; z-index: 0;"></div> </div> </div> <div style=" background: #b3ecb3; margin-top: 32px; margin-left: 40px;"> <div style="position: relative"> <div style="width: 40px; height: 40px; background: #ff0000; position: relative; z-index: 0;"></div> </div> </div> 

image

Ici, les contextes enfants sont extraits des flottants et des blocs ordinaires, tandis que l'ordre est conservé tel qu'il était dans l'arborescence d'origine.

Enfin, le dernier exemple:

 <div style="background: #b3ecf9;"> <div style="display: inline-block; width: 40px; height: 40px; background: #fc0;"></div> </div> <div style="background: #b3ecb3; margin-top: -100px; margin-left: 22px;"></div> 

image

Comme vous pouvez le voir, «sauter» d'un élément de bloc est, contrairement à d'autres cas, tout à fait possible, et puisque nous avons un élément de bloc en ligne qui apparaît, ce sera le dernier dans ce document.

Comme vous pouvez le voir, le z-index vous permet d'effectuer de nombreuses astuces intéressantes (ce qui vaut au moins cacher l'élément sous son parent immédiat en utilisant un z-index négatif sur l'enfant). J'espère que cet article vous a été utile.

Source: https://habr.com/ru/post/fr431046/


All Articles