Maison >interface Web >tutoriel CSS >Comment attendre les fonctions de frères et sœurs () et de soember-index ()

Comment attendre les fonctions de frères et sœurs () et de soember-index ()

William Shakespeare
William Shakespeareoriginal
2025-03-07 17:13:16240parcourir

How to Wait for the sibling-count() and sibling-index() Functions

Les nouvelles caractéristiques de CSS n'apparaissent pas à partir de l'air, mais passent par un long processus: discussion, évaluation, définition, écriture, prototypage, test, publication, soutien, etc. Ce processus est très long, et même si nous sommes impatients d'utiliser de nouvelles fonctionnalités, nous ne pouvons qu'attendre.

Mais nous pouvons choisir une autre façon d'attendre: éviter complètement les interfaces ou les démonstrations en utilisant cette fonctionnalité? Ou défier les limites du CSS et essayer de la mettre en œuvre vous-même?

De nombreux développeurs entreprenants et curieux ont choisi ce dernier. Sans cette mentalité, CSS stagnera. Aujourd'hui, nous explorerons deux fonctions à venir: sibling-count() et sibling-index(). Nous attendons avec impatience depuis de nombreuses années, alors laissez-moi laisser ma curiosité voler et ressentir leur charme à l'avance!

Fonction du nombre d'arbres

Vous avez peut-être dû savoir où se trouve un élément dans son élément de frère, ou le nombre d'éléments enfants qu'un certain élément a afin de calculer dans CSS, comme la mise en œuvre de certains animations entrelacées, chaque élément a un retard plus long ou modifiant la couleur d'arrière-plan de l'élément en fonction du nombre d'éléments de frère. Cela a longtemps été un projet tant attendu sur ma liste de souhaits CSS. Consultez ce numéro GitHub CSSWG 2017:

Demande de fonction. Ce serait formidable de pouvoir utiliser la fonction calc() dans la fonction counter(). Cela apportera de nouvelles possibilités à la mise en page.

Cependant, la fonction counter() utilise une chaîne, ce qui le rend inutile dans la fonction calc() qui gère les nombres. Nous avons besoin d'un ensemble similaire de fonctions qui renvoie l'indice d'un élément et son nombre d'éléments de frères sous la forme d'un entier . Cela ne semble pas être une examen excessive. Nous pouvons actuellement utiliser le :nth-child() pseudo-sélectionneur (et ses variantes) pour interroger les éléments en fonction des emplacements des arbres, sans parler de l'utilisation du pseudo-sélectionneur :has() pour interroger en fonction du nombre d'éléments que contient l'élément.

Heureusement, cette année, CSSWG a approuvé la mise en œuvre des fonctions sibling-count() et sibling-index()! Un contenu a été écrit dans la spécification:

La fonction

sibling-count() représente le nombre total d'éléments enfants dans l'élément parent de l'élément en utilisant la fonction, exprimée en <integer></integer>.

La fonction

sibling-index() représente l'index de l'élément en utilisant la fonction dans l'élément enfant de son élément parent, représenté par <integer></integer>. Similaire à :nth-child(), sibling-index() compte à partir de 1.

Combien de temps nous faudra-t-il pour les utiliser? Plus tôt cette année, Adam Argyle a déclaré: "Un ingénieur de chrome a mentionné vouloir faire cela, mais nous n'avons pas encore le logo pour l'essayer. Je vais le partager quand il y a des nouvelles!" En attendant, voyons ce que nous pouvons faire maintenant!

Mise à jour (5 mars 2025): Chrome a soumis l'intention de prototyper ces deux fonctions.

Méthode originale

En termes de syntaxe et d'utilisation, la chose la plus proche d'une fonction de nombre d'arbres est les propriétés personnalisées. Cependant, le plus gros problème est de savoir comment les remplir avec les index et comptes corrects. Le moyen le plus simple et le plus long est de coder en hard chaque valeur en utilisant des CS purs: nous pouvons utiliser le sélecteur nth-child() pour donner à chaque élément son index correspondant:

li:nth-child(1) {
  --sibling-index: 1;
}

li:nth-child(2) {
  --sibling-index: 2;
}

li:nth-child(3) {
  --sibling-index: 3;
}

/* 以此类推... */

Paramètre sibling-count() Les équivalents nécessitent plus de subtilités car nous devons utiliser le nombre de sélecteurs :has() pour interroger. La requête de quantité a la syntaxe suivante:

.container:has(> :last-child:nth-child(m)) { }

… où m est le nombre d'éléments que nous voulons localiser. Il fonctionne en vérifiant si le dernier élément du conteneur est également le nième élément que nous positionnons; donc il n'a que tant d'éléments. Vous pouvez utiliser cet outil à partir de Temani AFIF pour créer votre propre requête de quantité. Dans ce cas, notre requête de quantité ressemble à ceci:

ol:has(> :nth-child(1)) {
  --sibling-count: 1;
}

ol:has(> :last-child:nth-child(2)) {
  --sibling-count: 2;
}

ol:has(> :last-child:nth-child(3)) {
  --sibling-count: 3;
}

/* 以此类推... */

Pour la concision, cet exemple ne contient délibérément qu'un petit nombre d'éléments, mais à mesure que la liste se développe, elle deviendra difficile à gérer. Peut-être que nous pouvons utiliser des préprocesseurs comme Sass pour les écrire pour nous, mais nous voulons nous concentrer sur des solutions CSS pures ici. Par exemple, la démonstration suivante peut prendre en charge jusqu'à 12 éléments, et vous pouvez déjà voir à quel point le code est laid.

Pour ceux qui marquent, il faut 24 règles pour comprendre l'indice et le nombre de 12 éléments. Nous pensons certainement que nous pouvons réduire ce nombre à des nombres plus gérables, mais si nous cocodions à chaque index, nous augmentons la quantité de code que nous écrivons. La meilleure chose que nous puissions faire est de réécrire nos CSS afin que nous puissions nicher les propriétés --sibling-index et --sibling-count ensemble. Au lieu d'écrire chaque attribut séparément:

li:nth-child(2) {
  --sibling-index: 2;
}

ol:has(> :last-child:nth-child(2)) {
  --sibling-count: 2;
}

Nous pouvons nicher les règles --sibling-count dans les règles --sibling-index.

li:nth-child(2) {
  --sibling-index: 2;

  ol:has(> &:last-child) {
    --sibling-count: 2;
  }
}

Bien qu'il semble étrange de nidiquer l'élément parent à l'intérieur de son élément enfant, le code CSS suivant est complètement valide; Quelle syntaxe est plus facile à gérer? Cela dépend de vous. li li Mais ce n'est qu'un peu d'amélioration. Si nous avons 100 éléments, nous devons toujours coder les propriétés ol et

100 fois. Heureusement, la méthode suivante ajoutera des règles de manière logarithmique, en particulier avec la base 2. Donc, au lieu d'écrire 100 règles pour 100 éléments, nous n'avons qu'à écrire environ 100 règles pour environ 100 éléments.

--sibling-index Méthode d'amélioration --sibling-count

Cette méthode a été décrite pour la première fois par Roman Komarov en octobre de l'année dernière, où il prototype les deux fonctions du nombre d'arbres et les fonctions futures

. C'est un excellent article, donc je vous recommande fortement de le lire.

Cette méthode utilise également des propriétés personnalisées, cependant, au lieu de chaque propriété à code dur, nous utiliserons deux propriétés personnalisées pour construire la propriété --sibling-index de chaque élément. Pour être cohérent avec les articles de Roman, nous les appelons --si1 et --si2, tous deux à partir de 0:

li:nth-child(1) {
  --sibling-index: 1;
}

li:nth-child(2) {
  --sibling-index: 2;
}

li:nth-child(3) {
  --sibling-index: 3;
}

/* 以此类推... */

Le réel --sibling-index sera construit en utilisant ces deux propriétés et un facteur (F), qui représente un entier supérieur ou égal à 2, qui nous indique le nombre d'éléments qui peuvent être sélectionnés en fonction de la formule sqrt(F) - 1. Alors ...

  • Pour le facteur 2, nous pouvons sélectionner 3 éléments.
  • Pour le facteur 3, nous pouvons sélectionner 8 éléments.
  • Pour le facteur 5, nous pouvons sélectionner 24 éléments.
  • Pour le facteur 10, nous pouvons sélectionner 99 éléments.
  • Pour le facteur 25, nous pouvons sélectionner 624 éléments.

Comme vous pouvez le voir, l'augmentation du facteur de 1 augmentera le nombre d'éléments que nous pouvons choisir de façon exponentielle. Mais comment cela se traduit-il par CSS?

La première chose à savoir est que la formule pour calculer les attributs de --sibling-index est calc(F * var(--si2) var(--si1)). Si notre facteur est de 3, cela ressemble à ceci:

.container:has(> :last-child:nth-child(m)) { }

Le sélecteur ci-dessous peut être aléatoire, mais soyez patient avec moi pour expliquer. Pour l'attribut --si1, nous rédigerons une règle pour les éléments sélectionnés comme multiples du facteur et les compenserons par 1 jusqu'à ce que F - 1 soit atteint, puis définissez --si1 comme décalage. Cela se traduit par le CSS suivant:

ol:has(> :nth-child(1)) {
  --sibling-count: 1;
}

ol:has(> :last-child:nth-child(2)) {
  --sibling-count: 2;
}

ol:has(> :last-child:nth-child(3)) {
  --sibling-count: 3;
}

/* 以此类推... */

Donc, si notre facteur est de 3, nous rédigeons les règles suivantes jusqu'à ce que nous atteignions F-1, c'est-à-dire 2 règles:

li:nth-child(2) {
  --sibling-index: 2;
}

ol:has(> :last-child:nth-child(2)) {
  --sibling-count: 2;
}

Pour l'attribut --si2, nous rédigerons des règles pour sélectionner des éléments avec le nombre d'éléments en lots en tant que facteurs (donc si notre facteur est 3, nous sélectionnerons 3 éléments par règle), en reculent à partir du dernier indice possible (8 dans ce cas) jusqu'à ce que nous ne puissions plus sélectionner plus d'éléments en lots. C'est un peu compliqué à écrire dans CSS:

li:nth-child(2) {
  --sibling-index: 2;

  ol:has(> &:last-child) {
    --sibling-count: 2;
  }
}

De même, si notre facteur est de 3, nous écrivons les deux règles suivantes:

li {
  --si1: 0;
  --si2: 0;
}

c'est tout! En définissant uniquement les valeurs --si1 et --si2, nous pouvons calculer jusqu'à 8 éléments. Les calculs mathématiques de leur fonctionnement semblent bizarres à première vue, mais une fois que vous le comprenez intuitivement, tout est clair. J'ai fait cette démo interactive où vous pouvez voir comment accéder à tous les éléments à l'aide de cette formule. Survolez l'extrait de code pour voir quels éléments vous pouvez sélectionner et cliquer sur chaque extrait de code pour les combiner dans un index possible.

Si vous ajustez les éléments et les facteurs au maximum, vous verrez que nous pouvons sélectionner 48 éléments avec seulement 14 extraits de code!

etc., il manque une chose: sibling-count() fonction. Heureusement, nous réutiliserons tout ce que nous avons appris du prototypage sibling-index(). Nous commencerons avec deux propriétés personnalisées: --sc1 et --sc1 dans le conteneur, et les deux commencent également avec 0. La formule de calcul --sibling-count est la même.

li:nth-child(1) {
  --sibling-index: 1;
}

li:nth-child(2) {
  --sibling-index: 2;
}

li:nth-child(3) {
  --sibling-index: 3;
}

/* 以此类推... */

L'article de Roman explique également comment écrire des sélecteurs pour les attributs --sibling-count séparément, mais nous utiliserons la méthode de sélection :has() dans notre première technique afin que nous n'ayons pas à écrire des sélecteurs supplémentaires. Nous pouvons enfiler ces propriétés --sc1 et --sc2 dans les règles que nous définissons sibling-index() Propriétés:

.container:has(> :last-child:nth-child(m)) { }

Ceci utilise le facteur 3, nous pouvons donc calculer jusqu'à huit éléments avec seulement quatre règles. L'exemple suivant a un facteur 7, nous pouvons donc calculer jusqu'à 48 éléments avec seulement 14 règles.

Cette méthode est géniale, mais probablement pas pour tout le monde parce qu'elle fonctionne presque magique ou simplement parce que vous ne le trouvez pas esthétiquement agréable. Bien que cela soit facile pour ceux qui souhaitent faire du feu avec du silex et de l'acier, beaucoup de gens ne peuvent pas allumer leur feu.

Méthode JavaScript

Pour cette approche, nous utiliserons à nouveau des propriétés personnalisées pour simuler la fonction de nombre d'arborescence, et surtout, nous écrirons moins de 20 lignes de code pour calculer à l'infini - ou je dirais que 1.7976931348623157E 308, qui est la limite pour les numéros de point flottants à double précision!

Nous utiliserons l'API de l'observateur de mutation, donc bien sûr, JavaScript est requis. Je sais que c'est comme admettre l'échec à beaucoup de gens, mais je ne suis pas d'accord. Si la méthode JavaScript est plus simple (ce qui est en effet vrai dans ce cas), c'est le choix le plus approprié. Soit dit en passant, si les performances sont votre principale préoccupation, respectez le code dur de chaque index dans CSS ou HTML.

Tout d'abord, nous obtiendrons notre conteneur du dom:

ol:has(> :nth-child(1)) {
  --sibling-count: 1;
}

ol:has(> :last-child:nth-child(2)) {
  --sibling-count: 2;
}

ol:has(> :last-child:nth-child(3)) {
  --sibling-count: 3;
}

/* 以此类推... */

Nous créerons ensuite une fonction qui définit l'attribut --sibling-index dans chaque élément et --sibling-count dans le conteneur (il sera disponible pour les éléments enfants en raison de la cascade). Pour --sibling-index, nous devons itérer sur elements.children, et nous pouvons obtenir elements.children.length de --sibling-count.

li:nth-child(2) {
  --sibling-index: 2;
}

ol:has(> :last-child:nth-child(2)) {
  --sibling-count: 2;
}

Une fois que nous avons notre fonction, n'oubliez pas de l'appeler une fois afin que nous ayons la propriété initiale du nombre d'arborescence:

li:nth-child(2) {
  --sibling-index: 2;

  ol:has(> &:last-child) {
    --sibling-count: 2;
  }
}

Enfin, Mutation Observer. Nous devons initialiser un nouvel observateur à l'aide du constructeur MutationObserver. Il accepte une fonction de rappel qui s'appelle chaque fois que l'élément change, nous avons donc écrit la fonction updateCustomProperties. En utilisant l'objet Observer généré, nous pouvons appeler sa méthode observe(), qui accepte deux paramètres:

  1. les éléments que nous voulons observer, et
  2. un objet de configuration qui définit ce que nous voulons observer à travers trois propriétés booléennes: attributes, childList et subtree. Dans ce cas, nous voulons simplement vérifier les modifications dans childList, nous définissons donc la propriété sur true:
li:nth-child(1) {
  --sibling-index: 1;
}

li:nth-child(2) {
  --sibling-index: 2;
}

li:nth-child(3) {
  --sibling-index: 3;
}

/* 以此类推... */

C'est tout ce que nous devons faire! En utilisant cette méthode, nous pouvons calculer de nombreux éléments , dans la démonstration suivante, j'ai réglé la valeur maximale sur 100, mais elle atteint facilement dix fois:

Alors oui, c'est notre lance-flammes. Il enflamme certainement la flamme, mais pour la grande majorité des cas d'utilisation, il est trop puissant. Mais c'est ce que nous avons lorsque nous attendons le briquet parfait.

Que ferez-vous ensuite?

Je n'ai pas de machine à remonter le temps, donc je ne peux pas dire quand les fonctions sibling-index() et sibling-count() seront publiées. Cependant, CSSWG a écrit quelque chose dans la spécification, et l'intention du navigateur (principalement du chrome) de publier des choses a été très forte ces derniers temps, donc je crois que nous verrons ces deux fonctions bientôt!

Heureusement, une fois qu'ils sont publiés et que le support est acceptable, il vous suffit de définir ces propriétés personnalisées sur le même nom que leur fonction. Bien sûr, si vous ne souhaitez pas modifier CSS pour modifier chaque attribut personnalisé, vous pouvez également le faire:

.container:has(> :last-child:nth-child(m)) { }
Plus d'informations et tutoriels

    CSS futur possible: fonctions de comptage d'arbres et valeurs aléatoires (Komarov romain)
  • Voir les transitions stupéfiantes (Chris Coyier)
  • Index des éléments (Chris Coyier)
Questions connexes

    Activer l'utilisation de compteur () à l'intérieur de calc () # 1026
  • Proposition: Ajouter un coup de frère () et Sibling-Index () # 4559
  • Étendre Sibling-Index () et Sibling-Count () avec un argument sélecteur # 9572
  • Proposition: Children-Count () Fonction # 11068
  • Proposition: Fonction descendante-Count () # 11069
Cette sortie révisée maintient l'image d'origine et son format, reformulez les phrases et les paragraphes pour paraphraser sans modifier le sens central et utilise un langage plus concis et engageant.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:La machine de siArticle suivant:La machine de si