Gestion de ZIndex dans une application Web basée sur des composants
À propos de l'auteur
Pavel Pomerantsev s'occupe de l'écriture de code et n'a que la compréhension la plus superficielle de la vie au-delà de la plate-forme Web. Vous pouvez trouver plus…
Pour en savoir plus sur Pavel …
z-index
malgré tout ce qui est écrit à ce sujet, est encore largement mal comprise et mal gérée. Les problèmes d'empilement dans une application Web complexe d'une seule page peuvent devenir un problème majeur. En adhérant à certains principes, cependant, nous pouvons facilement éviter ces problèmes.
Si vous avez déjà développé une interface utilisateur Web complexe, vous devez au moins avoir essayé de conduire avec fureur le [z-indexde] d'un élément
jusqu'à des milliers, seulement pour voir que cela n'aide pas à le positionner au-dessus d'un autre élément, dont le z-index
est inférieur ou même pas défini du tout.
Pourquoi cela se produit-il? Et plus important encore, comment éviter de tels problèmes?
Dans cet article, je vais récapituler ce que z-index
est réellement et comment vous pouvez arrêter de deviner si cela pourrait fonctionner dans un cas spécifique et commencer à traiter
La hiérarchie des contextes d'empilement
Si vous imaginez que la page Web a trois dimensions, alors z-index
est une propriété qui définit le z [index].
coordonnée d'un élément (également appelée son "ordre d'empilement"): plus la valeur est grande, plus l'élément est proche de l'observateur. Vous pouvez également le considérer comme une propriété affectant l'ordre de la peinture. Ce sera en fait plus correct car l'écran est une grille bidimensionnelle de pixels. Ainsi, plus la valeur de z-index
est grande, plus l'élément est peint ultérieurement sur la page.
Il existe toutefois une complication majeure. L’espace de valeurs z-index
n’est pas plat, c’est hiérarchique. Un élément peut créer un contexte d'empilement qui devient la racine des valeurs de z-index
de ses descendants. Il serait préférable d'expliquer le concept de contextes d'empilement à l'aide d'un exemple
Le corps du document compte cinq div
descendants: div1
div2
div3
div1-1
et div2-1
. Ils sont tous parfaitement positionnés et se chevauchent. div1-1
est un enfant de div1
et div2-1
est un enfant de div2
.
Voir le stylo [] empilement-contextes de Pavel Pomerantsev .
Essayons de comprendre pourquoi nous voyons ce que nous voyons. Il existe des règles assez élaborées pour déterminer l'ordre de peinture mais il suffit ici de comparer deux choses:
z-index
Valeurs
Si un élément a une valeur plus élevéez- index
il est peint plus tard.- Ordre de la source
Siles valeurs de z-index
sont identiques, alors plus tard elles sont dans la source, plus tard elles sont peintes.
Donc, si nous ne prenons pas en compte les contextes d'empilement, l'ordre devrait être le suivant:
Notez que div2-1
est en fait chevauché par div3
.
Si un élément crée un contexte d'empilement il crée une base pour les valeurs de son z-index
pour enfants, de sorte qu'il n'est jamais comparé à quoi que ce soit hors du contexte d’empilement lors de la détermination de l’ordre de peinture. En d'autres termes, lorsqu'un élément créant un contexte d'empilement est peint, tous ses enfants sont peints juste après et avant l'un de ses frères et soeurs.
Pour revenir à l'exemple, l'ordre de peinture réel de body [Ledescendantdivsde
est:
Remarquez l'absence de div2-1
dans la liste – il s'agit d'un enfant de div2
ce qui crée un contexte de superposition (parce que c'est un positionnement absolu). élément avec un z-index
autre que la valeur par défaut de auto
), il est donc peint après div2
mais avant div3
. [19659005] div1
ne crée pas de contexte d'empilement, car sa valeur z-index
implicite est auto
donc div1-1
(donc son enfant) est peint après div2
et div3
(depuis son z-index
10, est plus grand que celui de div2
et div3
).
Ne vous inquiétez pas si vous ne comprenez pas cela en première lecture. Il existe de nombreuses ressources en ligne qui expliquent ces concepts plus en détail:
Note : Il est également agréable de connaître les règles générales relatives à l'ordre des peintures . (qui sont en fait assez complexes).
Cependant, le point principal de cette pièce est de savoir comment traiter z-index
lorsque votre page est composée de dizaines et de centaines de composants, chacun Avoir potentiellement des enfants avec z-index
défini
L'un des articles les plus populaires sur z-index
propose regroupant toutes les valeurs de z-index
à un endroit mais comparer ces valeurs n'a pas de sens si elles n'appartiennent pas au même contexte d'empilement (ce qui peut ne pas être facile à obtenir dans une application volumineuse).
Voici un exemple. Disons que nous avons une page avec en-tête et sections principales. La section principale pour une raison quelconque doit avoir la position : relative
et z-index: 1
.
Nous utilisons ici une architecture de composant, donc CSS pour le composant racine et chaque composant enfant est défini dans des sections dédiées. En pratique, les composants vivraient dans des fichiers séparés et le balisage serait généré à l'aide d'une bibliothèque JavaScript de votre choix, telle que React, mais à des fins de démonstration, il est correct de tout avoir ensemble.
Imaginez maintenant que nous sommes chargés de créer un menu déroulant dans l'en-tête. Bien sûr, il doit être empilé au-dessus de la section principale. Nous allons donc lui attribuer un index-z
de 10
:
quelques mois plus tard, afin de rendre quelque chose de meilleur fonctionne mieux, nous appliquons le hack translateZ
à l'en-tête.
Comme vous pouvez le constater, la présentation est maintenant brisée. Un élément avec z-index: 1
repose sur un élément avec z-index: 10
en l'absence de toute autre règle z-index
. La raison en est que l'en-tête crée maintenant un contexte d'empilement – c'est un élément avec une propriété transform
dont la valeur est autre que none
( voir règles complètes ) et son propre z-index
( 0
par défaut) est inférieur à celui de la section principale ( 1
).
La solution est simple: donnez le header a La valeur z-index
de 2
est corrigée et le problème sera résolu.
La question est de savoir comment pouvons-nous arriver à cette solution si nous avons des composants dans des composants au sein de composants, chacun ayant des éléments avec différents indices z? Comment pouvons-nous être sûrs que changer z-index
de l'en-tête ne casse rien d'autre?
La réponse est une convention qui élimine le besoin de devinettes, et c'est la suivante: changer de z-indices dans un composant ne devrait affecter que ce composant et rien d'autre. En d'autres termes, lorsque nous traitons des valeurs de z-index
dans un certain fichier CSS, nous ne devrions idéalement nous préoccuper que des autres valeurs de ce même fichier.
Il est facile de l'atteindre. Nous devons simplement nous assurer que la racine de chaque composant crée un contexte d'empilement. La façon la plus simple de le faire est de lui donner les valeurs de position
et de z-index
autres que les valeurs par défaut (qui sont static
et auto
respectivement).
Voici l’un des moyens de structurer l’application. Il utilise plus d'éléments que le précédent, mais le calcul associé aux éléments supplémentaires du DOM est peu coûteux, alors que le temps nécessaire au développeur (dont une grande partie peut parfois être utilisée pour le débogage) ne l'est certainement pas.
header__container
etprincipal__container
les deux ontla position: relative
etl'indice z: 0
;header__overlay
a maintenantl'indice z: 1
pas besoin d'une grande valeur car il ne concurrencera que l'ordre d'empilement avec d'autres éléments dans l'en-tête);root__header
a maintenantz-index: 2
alors queroot__main
conserve sonz-index: 1
et c'est ce qui permet aux deux frères et sœurs de s'empiler correctement.
(Notez également qu'ils ont tous deux la position: relative
depuis L'indice z
ne s'applique pas aux éléments positionnés de manière statique .)
Si nous examinons le code d'en-tête Maintenant, nous remarquerons que nous pouvons supprimer la propriété z-index
du conteneur et de la superposition, parce que la superposition est le seul élément positionné . De même, le z-index
n'est pas requis sur le conteneur principal. C’est le principal avantage de l’approche proposée: lorsqu’on examine les indices z, c’est uniquement le composant qui compte, et non son contexte.
Une telle architecture n’est pas dépourvue d’inconvénients. Cela rend l'application plus prévisible au détriment d'une certaine souplesse. Par exemple, vous ne pourrez pas créer de telles superpositions à la fois dans l'en-tête et dans la section principale:
D'après mon expérience, toutefois, c'est rarement un problème. Vous pouvez faire en sorte que la superposition de la section principale soit réduite au lieu d'être augmentée, afin de ne pas croiser l'en-tête. Ou, si vous en aviez vraiment besoin, vous pouvez injecter le code HTML superposé à la fin du corps et lui attribuer un grand z-index
("grand" étant tout ce qui est plus grand que ceux des autres le niveau supérieur). Quoi qu'il en soit, si vous ne participez pas à une compétition pour construire la mise en page la plus compliquée, tout va bien.
Pour récapituler:
- Isoler les composants en termes de
z-index
valeurs d'éléments en faisant de la racine de chaque composant un contexte d'empilement; - Vous n'avez pas à le faire si aucun élément dans un composant n'a besoin d'une valeur
z-index
autre queauto
; - Dans le fichier CSS d'un composant, maintient
la valeur de z-index
à votre guise . Il peut s’agir de valeurs consécutives, ou vous pouvez leur attribuer une valeur de 10, ou vous pouvez utiliser des variables. Tout dépend des conventions de votre projet et de la taille du composant (bien que réduire les composants soit une bonne chose). De préférence, n'attribuez quez-index
aux éléments frères. Sinon, vous risquez d’introduire par inadvertance davantage de contextes d’empilement dans un composant et de faire face au même problème, heureusement à une plus petite échelle; - Le débogage devient facile . Trouvez le premier composant ancêtre des deux éléments qui ne sont pas empilés correctement et modifiez les indices z dans ce composant si nécessaire.
Nous espérons que cette approche ramènera un peu de bon sens à votre processus de développement.

Source link