355 votes

Peut CSS détecter le nombre d'enfants qu'un élément a?

Je réponds probablement à ma propre question, mais je suis extrêmement curieux.

Je sais que le CSS peut sélectionner des enfants individuels d'un parent, mais existe-t-il un support pour styliser les enfants d'un conteneur, si son parent a un certain nombre d'enfants.

par exemple

container:children(8) .child {
  //stylez les enfants de cette manière s'il y a 8 enfants
}

Je sais que cela semble étrange, mais mon gestionnaire m'a demandé de vérifier, je n'ai rien trouvé par moi-même donc j'ai décidé de me tourner vers SO avant de finir ma recherche.

4 votes

Mixin de requête de quantité SCSS: codepen.io/jakob-e/pen/wgGpeP

0 votes

Jun 3 '20 edit by @vsync devrait être annulé, car il modifie l'exemple de code d'une manière qui ne correspond en aucun cas à la question elle-même ou à ses réponses.

0 votes

@NikRolls - Ma modification ne doit pas être annulée. J'ai simplement condensé le problème à son essence - qui est comment sélectionner un parent selon le nombre de nœuds enfants qu'il a. Si vous pouvez le faire, alors évidemment, vous pouvez faire ce que l'OP voulait au départ, mais le noyau est ce sélecteur lui-même et non tout ce qui vient après.

784voto

Lübnah Points 1355

Clarification:

En raison d'une formulation antérieure dans la question d'origine, quelques citoyens de SO ont soulevé des inquiétudes selon lesquelles cette réponse pourrait être trompeuse. Notez que, en CSS3, les styles ne peuvent pas être appliqués à un nœud parent en fonction du nombre d'enfants qu'il contient. Cependant, les styles peuvent être appliqués aux nœuds enfants en fonction du nombre de frères et sœurs qu'ils ont.


Réponse originale:

Incroyablement, c'est désormais possible uniquement en CSS3.

/* un élément */
li:first-child:nth-last-child(1) {
/* -ou- li:only-child { */
    width: 100%;
}

/* deux éléments */
li:first-child:nth-last-child(2),
li:first-child:nth-last-child(2) ~ li {
    width: 50%;
}

/* trois éléments */
li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    width: 33.3333%;
}

/* quatre éléments */
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
    width: 25%;
}

Le truc consiste à sélectionner le premier enfant lorsqu'il est également le énième enfant depuis la fin. Cela permet de sélectionner efficacement en fonction du nombre de frères et sœurs.

Le crédit de cette technique revient à André Luís (découverte) & Lea Verou (affinée).

Vous aimez simplement CSS3, n'est-ce pas?

0 votes

L'OP a depuis édité sa question également. J'ai nettoyé les commentaires, mais pour des raisons de clarté, je pense que je laisserai votre édition. Vous pouvez la rétablir de votre propre volonté si vous la trouvez superflue.

0 votes

@BoltClock Merci, j'ai mis à jour ma réponse pour réduire toute confusion future.

12 votes

Très pratique. J'ai écrit un mixin SASS qui utilise cette technique : codepen.io/anon/pen/pJeLdE?editors=110

50voto

derekerdmann Points 7597

Non. Enfin, pas vraiment. Il y a quelques sélecteurs qui peuvent vous rapprocher un peu, mais ils ne fonctionneront probablement pas dans votre exemple et n'ont pas la meilleure compatibilité entre navigateurs.

:only-child

Le sélecteur :only-child est l'un des rares sélecteurs de comptage réel dans le sens où il s'applique uniquement lorsqu'il y a un enfant du parent de l'élément. En utilisant votre exemple idéalisé, il agit probablement comme le ferait children(1).

:nth-child

Le sélecteur :nth-child pourrait en fait vous mener là où vous voulez aller en fonction de ce que vous cherchez vraiment à faire. Si vous souhaitez styliser tous les éléments s'il y a 8 enfants, vous êtes malchanceux. En revanche, si vous souhaitez appliquer des styles aux 8ème et aux éléments suivants, essayez ceci :

p:nth-child( n + 8 ){
    /* ajouter des styles pour le rendre joli */
}

Malheureusement, ce ne sont probablement pas les solutions que vous recherchez. À la fin, vous devrez probablement utiliser un peu de magie Javascript pour appliquer les styles en fonction du décompte - même si vous deviez en utiliser un de ces, vous devriez sérieusement envisager la compatibilité entre navigateurs avant d'opter pour une solution purement CSS.

Spécification W3 CSS3 sur les pseudo-classes

ÉDITION J'ai lu votre question un peu différemment - il y a quelques autres façons de styliser le parent, pas les enfants. Laissez-moi vous proposer quelques autres sélecteurs :

:empty et :not

Cela stylise les éléments qui n'ont pas d'enfants. Ce n'est pas très utile par lui-même, mais lorsqu'il est associé au sélecteur :not, vous pouvez styliser uniquement les éléments qui ont des enfants :

div:not(:empty) {
    /* Nous savons qu'il contient des choses ! */
}

Vous ne pouvez pas compter le nombre d'enfants disponibles en CSS pur ici, mais c'est un autre sélecteur intéressant qui vous permet de faire des choses intéressantes.

0 votes

Il convient de noter que la question originale a été modifiée, rendant le premier "Non" un peu trompeur (juste pour info)

22voto

ifugu Points 88

NOTE: Cette solution renverra les enfants d'ensembles de certaines longueurs, et non pas l'élément parent comme vous l'avez demandé. Espérons que cela soit encore utile.

Andre Luis a trouvé une méthode: http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/ Malheureusement, cela ne fonctionne que dans IE9 et versions ultérieures.

Essentiellement, vous combinez :nth-child() avec d'autres pseudo-classes qui traitent de la position d'un élément. Cette approche vous permet de spécifier des éléments provenant de ensembles d'éléments de longueurs spécifiques.

Par exemple :nth-child(1):nth-last-child(3) correspond au premier élément dans un ensemble tout en étant le 3ème élément depuis la fin de l'ensemble. Cela garantit que l'ensemble comporte uniquement trois éléments et que nous avons le premier des trois. Pour spécifier le deuxième élément de l'ensemble de trois éléments, on utiliserait :nth-child(2):nth-last-child(2).

Exemple 1 - Sélectionner tous les éléments de liste si l'ensemble comporte trois éléments:

li:nth-child(1):nth-last-child(3),
li:nth-child(2):nth-last-child(2),
li:nth-child(3):nth-last-child(1) {
    width: 33.3333%;
}

Alternative de l'exemple 1 de Lea Verou:

li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    width: 33.3333%;
}

Exemple 2 - cibler le dernier élément d'un ensemble avec trois éléments de liste:

li:nth-child(3):last-child {
    /* Je suis le dernier des trois */
}

Alternative de l'exemple 2:

li:nth-child(3):nth-last-child(1) {
    /* Je suis le dernier des trois */
}

Exemple 3 - cibler le deuxième élément d'un ensemble avec quatre éléments de liste:

li:nth-child(2):nth-last-child(3) {
    /* Je suis le deuxième des quatre */
}

1 votes

Encore, ceci est le nombre de frères et sœurs, pas d'enfants

0 votes

@TMS voir l'édition de la réponse acceptée - la question du poseur était maladroitement formulée

0 votes

Cette approche est parfaite lorsque chaque élément doit être stylisé différemment en fonction de sa position dans la liste, par exemple pour obtenir des transformations circulaires uniformes : li:nth-child(3):nth-last-child(1) { transform: rotate(120deg); } li:nth-child(2):nth-last-child(2) { transform: rotate(240deg); } et ainsi de suite...

6voto

AlanFoster Points 3437

Oui, nous pouvons le faire en utilisant nth-child comme ceci :

div:nth-child(n + 8) {
    background: red;
} 

Cela fera que le 8ème enfant div et les suivants deviendront rouges. J'espère que cela vous aidera...

Aussi, si quelqu'un dit un jour "hey, cela ne peut pas être fait en utilisant du css, utilisez du JS!" doutez immédiatement. Le CSS est extrêmement flexible de nos jours

.container div {
  background: blue;
}

.container div:nth-child(n + 8) {
  background: red;
}

  div 1
  div 2
  div 3
  div 4
  div 5
  div 6
  div 7
  div 8
  div 9
  div 10
  div 11
  div 12

Dans l'exemple, les 7 premiers enfants sont en bleu, puis à partir du 8ème ils sont en rouge...

[Exemple externe]

1 votes

Peut-être ajouter une note sur le regrettable manque de support ?

2 votes

Je ne pense pas que ce soit exactement ce que Brodie demande - cela va styliser les enfants après un certain montant donné, mais ne peut pas sélectionner l'ancêtre/l'élément contenant en fonction du nombre de ses enfants.

0 votes

C'est en fait de très bonnes informations, merci Alan mais bee a raison, je voulais dire "si un élément a autant d'enfants, utilisez ce style". Si je ne me trompe pas, votre méthode styliserait le 8e enfant, mais les 7 premiers seraient seuls et nus.

1voto

Niet the Dark Absol Points 154811

Non, il n'y a rien de tel en CSS. Vous pouvez cependant utiliser JavaScript pour calculer le nombre d'enfants et appliquer des styles.

1 votes

@Lübnah Pouvez-vous expliquer pourquoi ce n'est pas vrai?

1 votes

@GabrielSantos (John regarde une pomme rouge). -John: Je vois une pomme bleue. -Max: Ce n'est pas vrai, elle est rouge. -John Peux-tu expliquer pourquoi ce n'est pas vrai?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X