Fermer

février 10, 2021

Gestion de l'index CSS Z dans les grands projets


À propos de l’auteur

Steven Frieson est un développeur frontal qui aime résoudre les problèmes des gens, qu’ils soient des utilisateurs de sites Web ou des collègues développeurs. Il s'intéresse à beaucoup…
En savoir plus sur
Steven

La résolution des valeurs d'index z est une tâche difficile pour de nombreux développeurs. Voici un mini-framework facile à mettre en œuvre basé sur des conventions existantes qui apporte clarté et confiance au travail avec z-index.

Il existe plusieurs articles qui expliquent z-index ( en voici un bon ) ), car il continue de trébucher les développeurs de tous niveaux d'expérience. Je ne pense pas que le nombre d'articles soit le signe qu'aucun d'entre eux ne fait un bon travail pour l'expliquer, mais qu'il y a beaucoup de développeurs là-bas et que le simple fait qu'un développeur ait lu et compris l'article ne signifie pas nécessairement que tout le monde dans son équipe le lit et le comprend maintenant. Tout en prenant le temps de mieux comprendre comment fonctionne z-index (ou tout autre élément de la technologie) vous permettra de mieux travailler avec lui, nous pouvons également adopter une autre approche: faciliter le travail avec z-index .

Nous utilisons des abstractions et des conventions pour cacher les parties délicates et sujettes aux erreurs, ce qui facilite la tâche à tous ceux qui doivent faire la même tâche. J'ai eu l'occasion d'essayer de rendre z-index plus facile à utiliser pour mon équipe tout en travaillant sur la refonte du site Web de notre entreprise. Le système que j'ai conçu a permis à mon équipe d'implémenter toute l'interface utilisateur sans jamais avoir à se demander à quoi une certaine valeur z-index était utilisée, quel numéro utiliser lors de l'ajout d'une nouvelle déclaration z-index, ou comment corriger les bogues d'empilement qui se sont glissés dans

Solution commune

Le système le plus courant que j'ai vu pour gérer les valeurs de z-index – autre que pas de système – est de définir plusieurs valeurs d'usage général, chacune séparée par un nombre arbitraire. Cette solution apprivoise définitivement les problèmes de z-index, mais comme j'ai travaillé avec des équipes qui utilisent ce système, il semble toujours y avoir une confusion sur la façon de l'utiliser correctement. Voici un exemple tiré de de la documentation Bootstrap .

 $ zindex-dropdown: 1000;
$ zindex-sticky: 1020;
$ zindex-fixed: 1030;
$ zindex-modal-backdrop: 1040;
$ zindex-modal: 1050;
$ zindex-popover: 1060;
$ zindex-tooltip: 1070;

Bootstrap définit les valeurs d'index z dans les variables Sass comme $ zindex-dropdown $ zindex-sticky et $ zindex-fixed . Ces noms semblent assez simples, mais lorsqu'un développeur choisit une valeur pour une fonctionnalité sur laquelle il travaille, il peut y avoir confusion quant à la valeur la plus appropriée pour son utilisation. Ils finissent par demander: "Est-ce que ce que j'implémente est un" menu déroulant "ou un" popover "?" qui peut facilement être débattue et peut ne pas avoir de réponse claire.

Un deuxième problème que je vois avec cette solution est que les valeurs réelles des variables peuvent sembler déroutantes ou conduire à l'insécurité. Cette solution laisse un espace entre chaque valeur pour donner aux développeurs l'espace pour ajouter leurs propres valeurs entre les deux si nécessaire. Bootstrap définit sept valeurs séparées par des incréments de 10, commençant à 1000 et se terminant à 1070.

De nombreuses questions pourraient venir à l'esprit en lisant ceci:

"Pourquoi commencer à 1000?

" Y a-t-il quelque chose de moins de 1000 ? »

« Où est 1010? Est-ce un bug? Est-ce que quelque chose d'autre l'utilise? »

« Pourquoi a-t-on choisi 10? Et si j’ai besoin de plus de 9 valeurs entre les deux? »

Bien que je n’ai jamais eu besoin de réponses à ces questions« et si », elles peuvent ajouter de l’insécurité et de la confusion à un système qui semble déjà magique et incompris. Pouvons-nous supprimer tous ces problèmes, permettant au développeur de choisir facilement et avec précision la valeur d'index z dont il a besoin?

Une nouvelle solution

Étant donné que travailler sur une refonte a donné à mon équipe un nouveau départ, c'était un problème courant nous voulions voir si nous pouvions éviter. Pour s'aligner sur nos normes générales de codage, mes objectifs de gestion de z-index étaient d'éviter les nombres magiques et de permettre à chaque membre de l'équipe de contribuer en toute confiance. Le deuxième objectif de faciliter les choses pour les autres est vague, donc je me suis concentré sur essayer de résoudre ces problèmes courants:

  • Les gens choisissent souvent des valeurs d'index z arbitrairement grandes;
  • Les corrections de bogues z-index entraînent souvent un nouveau z -index bug;
  • La relation entre les valeurs d'index z est difficile à tracer.

Regardons les solutions pour chacun de ces problèmes que j'ai pu appliquer, en m'appuyant sur les conventions et en utilisant les technologies existantes.

Donner Sémantique des valeurs d'index Z

Une des raisons pour lesquelles les gens choisissent souvent des valeurs d'index z arbitrairement grandes est qu'ils ne connaissent pas la valeur d'index z de l'élément au-dessus duquel ils essaient de placer un nouvel élément. Une fois qu'ils trouvent une valeur arbitrairement élevée qui fonctionne, ils la quittent au lieu de trouver une valeur optimale. Plus tard, quand quelqu'un trouve cette valeur, il n'a aucune idée de la raison pour laquelle c'est ce que c'est, et même l'auteur original peut avoir oublié.

 z-index: 9999; 

La solution pour corriger les «nombres magiques» comme ceci est d'utiliser à la place une constante nommée . Bien que nommer la valeur seule ne nous donne pas beaucoup plus de valeur que le nom de classe, lorsque nous mettons ensemble nos constantes d'index z, leur relation commence à devenir explicite.

Pour supprimer les nombres magiques, j'ai d'abord commencé à définir tous les nos valeurs z-index dans un fichier JavaScript. J'ai utilisé un fichier JavaScript car notre application utilisait une solution CSS-in-JS, bien que cela et les idées de cet article puissent être implémentés avec des préprocesseurs de style comme les variables Sass ainsi qu'en CSS à l'aide de propriétés personnalisées.

 export const backdrop = 0;
export const openButton = 1;
export const dropdown = 2; 

Avec les constantes z-index, la valeur CSS n'a guère plus de sens et la valeur réelle est masquée.

 css`
  z-index: $ {toile de fond};
`; 

Cela rend également la valeur d'origine facile à trouver, révélant les constantes associées, mais il y a une amélioration supplémentaire qui peut être faite. Nous savons par le fonctionnement de z-index que ces valeurs sont liées les unes aux autres, donc nous pouvons changer nos constantes pour rendre cela plus apparent .

 export const backdrop = 0;
export const openButton = toile de fond + 1;
export const dropdown = openButton + 1; 

En utilisant une arithmétique simple, nous pouvons utiliser les constantes précédentes pour créer la constante suivante. En poussant cette idée un peu plus loin pour éliminer davantage l'ambiguïté, j'ai ajouté quelques constantes d'utilité pour que ces définitions se lisent davantage comme une phrase.

 const base = 0;
const ci-dessus = 1;

export const backdrop = base;
export const openButton = above + backdrop;
export const dropdown = above + openButton; 

Maintenant, quand quelqu'un voit une ligne comme z-index: $ {dropdown}; il peut chercher la définition de la liste déroulante et lire: "Le dropdown est au-dessus du bouton d'ouverture . »

Cela facilite la maintenance future des constantes. Chaque fois que vous avez une nouvelle valeur à ajouter, vous pouvez être sûr de l'ajouter au bon endroit.

 export const backdrop = base;
export const openButton = above + backdrop;
exportation const dropdown = above + openButton;
export const closeButton = ci-dessus + liste déroulante; // new 

La suppression de valeurs est également facile, mais vous devez vous rappeler de mettre à jour toutes les autres valeurs qui en dépendent. En utilisant JavaScript, le linter a mis en évidence cela pour moi.

L'empilement de tickets de bogue apparaît souvent qui dit quelque chose comme, "la liste déroulante se chevauche avec le bouton alors qu'il devrait être en dessous." Lorsque vous les rencontrez, le correctif est aussi simple que d'échanger les pointeurs de relation dans les définitions.

 export const backdrop = base;
exportation const dropdown = dessus + toile de fond;
export const openButton = above + dropdown;
export const closeButton = ci-dessus + liste déroulante; // ??? 

Maintenant que nous avons inversé l’ordre des z-index, nous remarquons un autre bogue potentiel avant même de vérifier le navigateur. Le bouton de fermeture peut maintenant entrer en conflit avec le bouton d'ouverture. Vous pouvez maintenant avoir les conversations nécessaires pour résoudre les bogues avant que quiconque voit un problème de production.

Un élément supplémentaire que j'ai trouvé utile dans de rares situations était un utilitaire pour placer des éléments ci-dessous ] autres. Pour éviter de mélanger ci-dessus et ci-dessous j'ai établi la règle selon laquelle ci-dessous ne doit être utilisé que pour des valeurs négatives.

 const base = 0;
const ci-dessus = 1;
const ci-dessous = -1;

export const backdrop = ci-dessous + liste déroulante;
exportation const dropdown = ci-dessous + bouton;
export const button = base; 

Dans ce système, chaque valeur d'index z est aussi élevée que nécessaire, et comme elle est choisie dynamiquement, vous n'êtes pas concerné par la valeur réelle. [19659016] Vous pouvez également supprimer et ajouter des valeurs en sachant en toute confiance comment cela affectera les autres éléments empilés.

Une fois que notre application s'est terminée avec une douzaine de constantes z-index, même si cela a commencé à devenir un peu déroutant d'avoir un

Organisation par contexte d'empilement

Quand on réfléchit au contexte d'empilement et à la façon dont les valeurs de chaque contexte d'empilement sont indépendantes des autres, cela ressemblait à d'autres solutions frontales pour une portée efficace. J'ai dessiné des similitudes avec d'autres modules JavaScript, composants, conception atomique et BEM . Ils essaient tous de résoudre des problèmes similaires sur la façon dont nous pouvons définir indépendamment les préoccupations, en les empêchant d'affecter d'autres domaines.

En m'inspirant de BEM, j'ai fait une convention de nommage de nos constantes pour mieux organiser les valeurs et apportez plus d'ordre à la liste plate des constantes. Le format que j'ai fini par utiliser avait un modèle comme celui-ci: z .

La partie z est un préfixe indiquant le fait que la valeur est destinée à être utilisée dans z-index déclarations, étant donné que nous avions d'autres constantes définies dans nos fichiers JavaScript comme des variables de couleur.

La partie est remplacée par le contexte d'empilement de noms auquel appartient la constante. Ceci est similaire au «bloc» dans BEM et, en pratique, partage presque toujours le même nom que le composant stylisé. La principale exception est le contexte d'empilement HTML racine qui est utilisé pour l'empilement des régions de page.

La dernière partie du format, est pour le nom de l'élément spécifique à positionner dans le contexte d'empilement et est plus similaire à «Élément» dans BEM.

Voici un exemple complet de ce à quoi cette convention de dénomination pourrait ressembler lorsqu'elle est ajoutée à ce dont nous avons parlé précédemment. Pour une version interactive, vous pouvez jouer avec le même exemple dans un CodePen:

See the Pen [Managing CSS Z-Index in Large Projects Demo] (https://codepen.io/smashingmag/pen/xxEvepz) par Steven Frieson .

See the Pen Managing CSS Z-Index in Large Projects Demo by Steven Frieson .

Pour les autres versions linguistiques, consultez ce référentiel .

 // Utils
const base = 0;
const ci-dessus = 1; // utilisez ceci pour toutes les valeurs au-dessus de la base
const ci-dessous = -1; // et ceci pour toutes les valeurs inférieures à la base

// Mise en page
export const zLayoutNavigation = above + base;
export const zLayoutFooter = above + base;
export const zLayoutModal = above + zLayoutNavigation;
export const zLayoutPopUpAd = above + zLayoutModal;

// NavMenu
export const zNavMenuBackdrop = ci-dessous + base;
export const zNavMenuPopover = above + base;
export const zNavMenuToggle = above + zNavMenuPopover; 

Maintenant que nos constantes sont organisées en fonction de leur contexte d'empilement, nous pouvons rapidement voir quelles valeurs sont liées et où une nouvelle valeur ou un correctif devrait aller.

Aller plus loin

Cela est essentiellement la spécification de la façon dont cela devrait fonctionner. Étant donné que cette solution n'a été conçue que avec une seule application à l'esprit il y a quelques étapes supplémentaires qui pourraient être prises pour la rendre plus mature et prendre en charge plus de cas d'utilisation. Certaines de ces idées sont plus spécifiques au langage dans lequel elles sont implémentées, mais la plupart des idées sont conservées.

Un domaine qui pourrait éventuellement être amélioré autour de ce qui est expédié au navigateur. Lorsque j'ai implémenté cela, le framework que nous utilisions ne nous donnait pas beaucoup de contrôle sur les outils de construction, donc le fichier JavaScript de toutes les définitions était fourni avec l'application. Cela n'a pas eu d'impact mesurable sur les performances de notre application, mais vous avez peut-être remarqué que toutes les valeurs pouvaient être calculées au moment de la compilation. Une implémentation utilisant Sass finirait par ne livrer aucune des variables Sass au client, mais à la place, insérer la valeur z-index dérivée dans le CSS. Pour les solutions JS et CSS des outils de construction comme Webpack et PostCSS, respectivement, pourraient aider à faire de même.

La façon dont la solution a évolué au fur et à mesure que j'y travaillais, les constantes z-index ont fini par un fichier. Cela a fini par être un excellent moyen de voir toutes les valeurs de z-index à travers l'application à la fois, ce qui facilite la recherche rapide des éventuels conflits d'empilement. Elles étaient également classées avec d'autres constantes de style comme les couleurs et la typographie il était donc logique de les avoir toutes définies ensemble à l'origine. Au fur et à mesure que le fichier grandissait, il a commencé à être organisé en interne en empilant le contexte comme expliqué ci-dessus. Étant donné que les contextes d'empilement sont souvent mappés à un composant, il a commencé à penser que chaque ensemble de constantes pouvait être colocalisé avec leur composant. Cela apporterait tous les avantages normaux de la colocalisation, en étant plus proche des fichiers dans lesquels ils sont utilisés, ce qui réduirait les frictions lors de la nécessité d'ajouter, de modifier et de supprimer des constantes. Nous ne l'avons jamais remanié, mais cela semble être une option viable à explorer.

Un élément supplémentaire a à voir avec l'ergonomie et l'expérience des développeurs. Les constantes sont toutes exportées sous forme de liste plate pour le moment. La convention de dénomination s'est inspirée de BEM, mais Sass et JavaScript nous permettent d'utiliser d'autres manières d'organiser nos données . Des cartes Sass ou des objets JavaScript ou des cartes auraient pu être utilisées pour organiser les valeurs de manière hiérarchique. Si nous avions toutes les valeurs dans un objet z cela aurait pu conduire à des instructions d'importation plus courtes. Nous aurions pu aller plus loin pour avoir un objet par contexte d'empilement également conduisant à un style d'utilisation plus proche de z.layout.navigation . Différents outils tels que TypeScript pourraient éviter de faire des fautes de frappe ici, bien que cela puisse représenter plus d’efforts que cela ne vaut la peine.

Nos résultats

Le système tel qu’il est décrit a été implémenté et déployé avec succès dans nos applications de production. En revoyant les objectifs, nous nous sommes définitivement débarrassés des chiffres magiques. En ce qui concerne la facilité et la confiance des développeurs, mon équipe a pu facilement ajouter de nouvelles valeurs d'index z et corriger les bogues avant et après le lancement sans craindre que les changements introduisent de nouveaux bogues. À plusieurs reprises, nous avons corrigé des bogues avant qu'ils ne soient classés.

Nous avons également pu éviter le problème de trouver un z-index aléatoire : 9999; . Bien que l'application ait des en-têtes collants, des boutons d'action flottants, des listes déroulantes, des modaux, des publicités contextuelles, et plus encore dans le contexte d'empilement, la valeur la plus élevée que nous avions était de 5. Même alors, personne ne le savait puisque les valeurs nous étaient toutes abstraites. dans les variables.

La résolution des problèmes liés à l'expérience des développeurs a abouti à un mini-framework z-index, aidant les gens à prendre la bonne décision avec moins d'effort et à agir plus rapidement.

Autre chose que nous avons remarqué, c'est que parfois nous assignions un z-index lorsque nous n'en avons pas nécessairement besoin. Puisque les contextes d'empilement peuvent être créés par plusieurs propriétés différentes, des déclarations comme position: sticky; peuvent agir de la même manière que setting z-index: 1; . Dans ces cas, nous avons quand même continué à ajouter une constante et une déclaration. Les conserver permettait une meilleure cohérence dans le système au lieu de permettre des cas particuliers, ce qui dégraderait la confiance quant à savoir si tout fonctionnait correctement ou non. Garder la liste des constantes complète a aidé à comprendre le système et mieux nous mettre en place pour réorganiser les valeurs si nécessaire.

Ce qu'il ne résout pas

Comme tout framework, il y a des parties qui ne font pas un bon travail à résoudre pour vous. Nommer les choses est encore difficile, et ce cadre exacerbe légèrement le problème en exigeant que vous nommiez toutes vos valeurs z-index. Même quand même, nous avons constaté que la clarté acquise a surmonté la corvée d'avoir à tous les nommer.

Ce système ne vous aide pas nécessairement à déterminer dans quel contexte d'empilement un bogue se trouve. Venir à travers un bogue z-index où vous ne 'ne sais pas où le nouveau contexte d'empilement est créé ou où la valeur de z-index est définie n'est pas résolu par ce framework, mais une fois que vous avez trouvé le problème, le chemin pour faire le correctif correct est clair.

Votre application

Les idées partagées ici devraient être exploitables dans la plupart des applications en fonction de votre solution de style et de la prise en charge du navigateur. Migrer pour utiliser ce système n'est pas très risqué car les contextes d'empilement sont déjà étendus individuellement; vous pouvez migrer un contexte tel qu'il existe déjà à la fois. Changer pour utiliser ces conventions vous oblige à décrire plus clairement ce que vous avez déjà dans votre application, en mettant en lumière ce qui peut actuellement sembler être un coin sombre et effrayant.

Si vos valeurs d'index z sont dans un état où vous êtes incertain de la plupart ou de la totalité d'entre eux, alors la meilleure façon de convertir vers ce système sera probablement de commencer par créer une constante pour chaque valeur dans une seule liste dans un seul fichier. Au fur et à mesure que les contextes d'empilement deviennent plus clairs, vous pouvez commencer à les regrouper et à les renommer (si nécessaire) pour vous conformer à la convention de dénomination.

Mon équipe ne travaillait pas avec des bibliothèques CSS externes ou des frameworks contenant des valeurs d'index z, mais cela pourrait éventuellement compliquer l'adoption de ce système. Espérons que les utilitaires soient suffisamment configurables pour gérer la plupart des utilisations et même incorporer les valeurs tierces dans le système.

Enfin, tous les exemples ici ont été écrits dans un seul fichier de valeurs z-index, mais vous pourrait colocaliser ces valeurs avec le composant pour établir un lien encore plus fort entre les deux. L'utilisation d'une convention de dénomination de fichier facilitera la recherche de toutes les valeurs dans l'application.

Essayez-le vous-même

Si vous rencontrez des difficultés pour gérer les valeurs de z-index sur votre site et que vous finissez par essayer ces suggestions, J'aimerais entendre parler de votre expérience . Ce mini-framework a été développé en quelques mois seulement et n'a été utilisé que dans une seule base de code de production, il y a donc certainement des cas d'utilisation et des opinions inexplorés qui pourraient être ajoutés ou modifiés.

 Smashing Editorial "width =" 35 "height = "46" loading = "lazy" decoding = "asynchrone (vf, yk, il)






Source link