Il CSS può rilevare il numero di figli di un elemento?


304

Probabilmente sto rispondendo alla mia domanda, ma sono estremamente curioso.

So che i CSS possono selezionare singoli figli di un genitore, ma esiste un supporto per lo stile dei figli di un contenitore, se il suo genitore ha un certo numero di figli.

per esempio

container:children(8) {
  // style the parent this way if there are 8 children
}

So che sembra strano, ma il mio manager mi ha chiesto di verificarlo, non ho trovato nulla da solo, quindi ho deciso di passare a SO prima di terminare la ricerca.


2
Query quantità SCSS Mixin: codepen.io/jakob-e/pen/wgGpeP
Jakob E

Risposte:


695

Una precisazione:

A causa di una frase precedente nella domanda originale, alcuni cittadini di SO hanno sollevato preoccupazioni sul fatto che questa risposta potrebbe essere fuorviante. Si noti che, in CSS3, gli stili non possono essere applicati a un nodo padre in base al numero di figli che ha. Tuttavia, gli stili possono essere applicati ai nodi figlio in base al numero di fratelli che hanno.


Risposta originale:

Incredibilmente, questo è ora possibile solo in CSS3.

/* one item */
li:first-child:nth-last-child(1) {
/* -or- li:only-child { */
    width: 100%;
}

/* two items */
li:first-child:nth-last-child(2),
li:first-child:nth-last-child(2) ~ li {
    width: 50%;
}

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

/* four items */
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
    width: 25%;
}

Il trucco è selezionare il primo figlio quando è anche l'ennesimo figlio dall'ultimo. Questo seleziona efficacemente in base al numero di fratelli.

Il merito di questa tecnica va a André Luís (scoperto) e Lea Verou (raffinato).

Non ti piace solo CSS3? 😄

Esempio di CodePen:

fonti:


7
Molto maneggevole. Ho scritto un mixin SASS che utilizza questa tecnica: codepen.io/anon/pen/pJeLdE?editors=110
SimpleJ

1
@IanSteffy Ho appena provato questo su Chrome 45.0.2454.85 (64-bit) e funziona benissimo ...?
Matthemattics,

2
Se funziona in codepen ma non con il mio progetto, allora è sicuramente colpa mia. Colpa mia. Questa risposta è corretta! Esatto, dico io!
Ian S,

3
Potrebbe essere bello aggiungere perché questo funziona, per le persone che non sono abituate a più pseudo-selettori (come ero fino ad ora;). Quello che sta succedendo qui è che questo seleziona il figlio che è allo stesso tempo figlio x dall'inizio / in alto e figlio y dalla fine. E quindi questo seleziona qualcosa solo se ci sono esattamente x + y bambini.
Legolas,

7
Nota che al posto di :first-child:nth-last-child(1)te puoi anche usare :only-child.
Adam Reis,

40

No. Beh, non proprio. Ci sono un paio di selettori che possono avvicinarti un po ', ma probabilmente non funzioneranno nel tuo esempio e non hanno la migliore compatibilità del browser.

:only-child

Il :only-childè uno dei pochi veri selettori di conteggio, nel senso che viene applicato solo quando v'è un bambino del genitore dell'elemento. Usando il tuo esempio idealizzato, si comporta come children(1)probabilmente.

:nth-child

Il :nth-childselettore potrebbe effettivamente portarti dove vuoi andare a seconda di cosa stai davvero cercando di fare. Se vuoi dare uno stile a tutti gli elementi se ci sono 8 bambini, sei sfortunato. Se, tuttavia, desideri applicare gli stili all'ottavo e agli elementi successivi, prova questo:

p:nth-child( n + 8 ){
    /* add styles to make it pretty */
}

Sfortunatamente, queste probabilmente non sono le soluzioni che stai cercando. Alla fine, probabilmente dovrai usare alcuni maghi Javascript per applicare gli stili in base al conteggio - anche se dovessi usare uno di questi, avresti bisogno di dare un'occhiata alla compatibilità del browser prima di andare con un puro Soluzione CSS.

W3 CSS3 Spec su pseudo-classi

EDIT Ho letto la tua domanda in modo leggermente diverso: ci sono un paio di altri modi per modellare il genitore , non i bambini. Consentitemi di aggiungere alcuni altri selettori a modo vostro:

:empty e :not

Questo stile elementi che non hanno figli. Non è utile da solo, ma se associato al :notselettore, puoi modellare solo gli elementi che hanno figli:

div:not(:empty) {
    /* We know it has stuff in it! */
}

Non puoi contare quanti bambini sono disponibili con CSS puro qui, ma è un altro selettore interessante che ti consente di fare cose interessanti.


Vale la pena notare che la domanda originale è stata modificata, rendendo il "No" iniziale un po 'fuorviante (solo fyi 😛)
Matthemattics,

18

NOTA: questa soluzione restituirà i figli di insiemi di determinate lunghezze, non l'elemento padre come richiesto. Speriamo che sia ancora utile.

Andre Luis ha trovato un metodo: http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/ Sfortunatamente, funziona solo in IE9 e versioni successive.

In sostanza, combini: nth-child () con altre pseudo classi che si occupano della posizione di un elemento. Questo approccio consente di specificare elementi da insiemi di elementi con lunghezze specifiche .

Ad esempio, :nth-child(1):nth-last-child(3)corrisponde al primo elemento in un set pur essendo anche il 3 ° elemento dalla fine del set. Questo fa due cose: garantisce che l'insieme ha solo tre elementi e che abbiamo il primo dei tre. Per specificare il secondo elemento del set di tre elementi, dovremmo usare :nth-child(2):nth-last-child(2).


Esempio 1: selezionare tutti gli elementi dell'elenco se set ha tre elementi:

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%;
}

Esempio 1 alternativa da Lea Verou:

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


Esempio 2: destinazione dell'ultimo elemento dell'insieme con tre elementi dell'elenco:

li:nth-child(3):last-child {
    /* I'm the last of three */
}

Esempio 2 alternativa:

li:nth-child(3):nth-last-child(1) {
    /* I'm the last of three */
}


Esempio 3: destinazione del secondo elemento dell'insieme con quattro elementi dell'elenco:

li:nth-child(2):nth-last-child(3) {
    /* I'm the second of four */
}

1
di nuovo, questo è il numero di fratelli, non di bambini
TMS

@TMS vedi la modifica della risposta accettata - la domanda del PO è stata formulata in modo imbarazzante
ifugu

Questo approccio è perfetto per quando ogni elemento deve essere disegnato in modo diverso in base alla sua posizione nell'elenco, ad esempio per ottenere anche trasformazioni circolari: li:nth-child(3):nth-last-child(1) { transform: rotate(120deg); } li:nth-child(2):nth-last-child(2) { transform: rotate(240deg); }e così via ...
Greg Smith,

11

Lavorando sulla soluzione di Matt, ho usato la seguente implementazione Compass / SCSS.

@for $i from 1 through 20 {
    li:first-child:nth-last-child( #{$i} ),
    li:first-child:nth-last-child( #{$i} ) ~ li {
      width: calc(100% / #{$i} - 10px);
    }
  }

Ciò consente di espandere rapidamente il numero di elementi.


4
Invece di questo potresti facilmente usare Flexbox ...
Michał Miszczyszyn il

6

sì, possiamo farlo usando nth-child in questo modo

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

Questo farà diventare l'ottavo div bambino in poi rosso. Spero che questo ti aiuti...

Inoltre, se qualcuno dice mai "ehi, non possono essere fatti con lo stile usando css, usa JS !!!" dubitarli immediatamente. Oggi i CSS sono estremamente flessibili

Esempio :: http://jsfiddle.net/uWrLE/1/

Nell'esempio i primi 7 bambini sono blu, quindi 8 in poi sono rossi ...


1
Forse aggiungere una nota sulla sfortunata mancanza di supporto ?
benesch,

2
Non penso che sia esattamente ciò che Brodie sta chiedendo: questo modellerà i bambini dopo un determinato importo, ma non può selezionare l'elemento antenato / contenente in base al numero dei suoi figli.
Ben Hull,

Questa in realtà è comunque una buona informazione, grazie alan ma l'ape ha ragione, stavo cercando di dire "se un elemento ha così tanti bambini in questo stile" Se non sbaglio il tuo metodo modellerebbe l'ottavo bambino, ma il i primi 7 sarebbero soli e nudi.
Brodie,

@primatology - L'unico browser che non supporta nth-child è IE <9. Tutti gli altri lo hanno supportato due o più versioni.
Rob

-1 Questo non renderà div il bambino rosso, questo renderà il div rosso in base al suo numero all'interno dei suoi fratelli ! Non è in alcun modo correlato al figlio del div!
TMS

5

Se lo farai in puro CSS (usando scss) ma hai elementi / classi diversi all'interno della stessa classe genitore puoi usare questa versione !!

  &:first-of-type:nth-last-of-type(1) {
    max-width: 100%;
  }

  @for $i from 2 through 10 {
    &:first-of-type:nth-last-of-type(#{$i}),
    &:first-of-type:nth-last-of-type(#{$i}) ~ & {
      max-width: (100% / #{$i});
    }
  }

-1

No, non c'è nulla di simile in CSS. Puoi, tuttavia, utilizzare JavaScript per calcolare il numero di figli e applicare gli stili.


1
@ Lübnah Puoi spiegare perché non è vero?
Gabriel Santos
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.