Czy CSS może wykryć liczbę dzieci elementu?

304

Prawdopodobnie odpowiadam na moje pytanie, ale jestem bardzo ciekawy.

Wiem, że CSS może wybierać pojedyncze dzieci rodzica, ale czy istnieje wsparcie w stylizowaniu dzieci kontenera, jeśli jego rodzic ma pewną liczbę dzieci.

na przykład

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

Wiem, że to brzmi dziwnie, ale mój menedżer poprosił mnie o sprawdzenie, nie znalazłem niczego na własną rękę, więc postanowiłem zwrócić się do SO przed zakończeniem wyszukiwania.

Brodie
źródło
2
Zapytanie ilościowe Mixin SCSS: codepen.io/jakob-e/pen/wgGpeP
Jakob E

Odpowiedzi:

695

Wyjaśnienie:

Z powodu wcześniejszego sformułowania w pierwotnym pytaniu kilku SO obywateli wyraziło obawy, że ta odpowiedź może być myląca. Zauważ, że w CSS3 style nie mogą być stosowane do węzła nadrzędnego na podstawie liczby jego potomków. Jednak style można zastosować do węzłów potomnych na podstawie liczby ich rodzeństwa .


Oryginalna odpowiedź:

Niesamowicie, jest to teraz możliwe wyłącznie w 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%;
}

Sztuką jest wybranie pierwszego dziecka, gdy jest ono także dzieckiem n-tym od ostatniego. To skutecznie wybiera na podstawie liczby rodzeństwa.

Podziękowania dla tej techniki należą André Luís (odkryty) i Lea Verou (wyrafinowany).

Nie lubisz tylko CSS3? 😄

Przykład CodePen:

Źródła:

Matematyka
źródło
7
Bardzo przydatny. Napisałem mikser SASS, który korzysta z tej techniki: codepen.io/anon/pen/pJeLdE?editors=110
SimpleJ
1
@IanSteffy Właśnie przetestowałem to na Chrome 45.0.2454.85 (64-bit) i działa dobrze…?
Matthemattics,
2
Jeśli działa w codepen, ale nie w moim projekcie, to z całą pewnością moja wina. Mój błąd. Ta odpowiedź jest poprawna! Zgadza się, mówię!
Ian S
3
Może warto dodać, dlaczego to działa, dla osób, które nie są przyzwyczajone do wielu pseudo selektorów (jak ja do tej pory;). To, co się tutaj dzieje, polega na tym, że wybiera to dziecko, które jest jednocześnie dzieckiem x od początku / góry i dzieckiem y od końca. A więc to wybiera coś tylko wtedy, gdy istnieją dokładnie x + y dzieci.
Legolas,
7
Zauważ, że zamiast :first-child:nth-last-child(1)ciebie możesz również użyć :only-child.
Adam Reis,
40

Nie. Niezupełnie. Istnieje kilka selektorów, które mogą zbliżyć cię do siebie, ale prawdopodobnie nie będą działać w twoim przykładzie i nie będą miały najlepszej kompatybilności z przeglądarką.

:only-child

Jest :only-childto jeden z niewielu prawdziwych selektorów liczących w tym sensie, że jest stosowany tylko wtedy, gdy istnieje jedno dziecko elementu nadrzędnego elementu. Korzystając z wyidealizowanego przykładu, działa on children(1)prawdopodobnie tak, jak by to zrobił.

:nth-child

:nth-childSelektor rzeczywistości może Cię tam, gdzie chcesz iść w zależności od tego, czego naprawdę chce robić. Jeśli chcesz stylizować wszystkie elementy, jeśli jest 8 dzieci, nie masz szczęścia. Jeśli jednak chcesz zastosować style do 8. i późniejszych elementów, spróbuj tego:

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

Niestety, prawdopodobnie nie są to rozwiązania, których szukasz. W końcu prawdopodobnie będziesz musiał użyć niektórych kreatorów JavaScript, aby zastosować style oparte na liczbie - nawet jeśli użyjesz jednego z nich, musisz rzucić okiem na kompatybilność przeglądarki, zanim przejdziesz do czystego Rozwiązanie CSS.

W3 CSS3 Spec na pseudoklasy

EDYTOWAĆ Przeczytałem twoje pytanie nieco inaczej - istnieje kilka innych sposobów na stylizację rodzica , a nie dzieci. Pozwól mi rzucić kilka innych selektorów na swój sposób:

:empty i :not

Stylizuje elementy, które nie mają dzieci. Sam w sobie nie jest to użyteczne, ale w połączeniu z :notselektorem możesz stylizować tylko te elementy, które mają dzieci:

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

Nie możesz policzyć, ile dzieci jest dostępnych z czystym CSS, ale jest to kolejny interesujący selektor, który pozwala robić fajne rzeczy.

derekerdmann
źródło
Warto zauważyć, że oryginalne pytanie zostało zredagowane, przez co początkowe „Nie” jest nieco mylące (po prostu fyi 😛)
Matthemattics
18

UWAGA: To rozwiązanie zwróci dzieci zestawów o określonych długościach, a nie element nadrzędny, o co prosiłeś. Mam nadzieję, że nadal jest przydatny.

Andre Luis wymyślił metodę: http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/ Niestety, działa tylko w IE9 i nowszych wersjach.

Zasadniczo łączysz: nth-child () z innymi pseudo klasami, które zajmują się pozycją elementu. To podejście pozwala określić elementy z zestawów elementów o określonych długościach .

Na przykład :nth-child(1):nth-last-child(3)dopasowuje pierwszy element w zestawie, będąc jednocześnie 3. elementem od końca zestawu. Robi to dwie rzeczy: gwarantuje, że zestaw ma tylko trzy elementy i że mamy pierwszy z trzech. Aby określić drugi element z zestawu trzech elementów, użylibyśmy :nth-child(2):nth-last-child(2).


Przykład 1 - Wybierz wszystkie elementy listy, jeśli zestaw ma trzy elementy:

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

Przykład 1 alternatywa z Lea Verou:

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


Przykład 2 - celuj w ostatni element zestawu trzema elementami listy:

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

Przykład 2 alternatywa:

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


Przykład 3 - docelowy drugi element zestawu z czterema elementami listy:

li:nth-child(2):nth-last-child(3) {
    /* I'm the second of four */
}
ifugu
źródło
1
ponownie jest to liczba rodzeństwa, a nie dzieci
TMS
@TMS patrz edycja zaakceptowanej odpowiedzi - pytanie OP było niezręcznie sformułowane
ifugu
To podejście jest idealne, gdy każdy element musi być inaczej stylizowany w zależności od jego pozycji na liście, np. Aby uzyskać nawet okrągłe transformacje: li:nth-child(3):nth-last-child(1) { transform: rotate(120deg); } li:nth-child(2):nth-last-child(2) { transform: rotate(240deg); }i tak dalej ...
Greg Smith
11

Pracując nad rozwiązaniem Matta, zastosowałem następującą implementację 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);
    }
  }

Pozwala to szybko zwiększyć liczbę przedmiotów.

mwtidd
źródło
4
Zamiast tego można łatwo korzystać z Flexboksa…
Michał Miszczyszyn,
6

tak, możemy to zrobić za pomocą n-tego dziecka

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

To sprawi, że dziecko 8-tej div stanie się czerwone. Mam nadzieję że to pomoże...

Ponadto, jeśli ktoś powie „hej, nie można tego zrobić za pomocą stylów za pomocą css, użyj JS !!!” zwątp w nie natychmiast. CSS jest obecnie niezwykle elastyczny

Przykład :: http://jsfiddle.net/uWrLE/1/

W przykładzie pierwszych 7 dzieci jest niebieskich, a następnie 8 jest czerwonych ...

AlanFoster
źródło
1
Może dodać notatkę o niefortunnym braku wsparcia ?
benesch
2
Nie sądzę, że właśnie o to pyta Brodie - to stylizuje dzieci po określonej ilości, ale nie może wybrać elementu nadrzędnego / zawierającego na podstawie liczby jego dzieci.
Ben Hull
To w rzeczywistości kilka dobrych informacji, dzięki Alan, ale pszczoła ma rację, próbowałem powiedzieć „jeśli element ma tak wiele dzieci w tym stylu”. Jeśli się nie mylę, metoda zastosowałaby styl dla 8. dziecka, ale pierwsze 7 byłoby samotnych i nagich.
Brodie
@primatology - Jedyną przeglądarką, która nie obsługuje n-tego dziecka, jest IE <9. Wszystkie pozostałe wspierały dwie wersje wstecz lub więcej.
Rob
-1 Nie spowoduje to, że div będzie czerwone, spowoduje, że div będzie czerwone na podstawie liczby w rodzeństwie ! Nie jest w żaden sposób związany z dzieckiem diva!
TMS
5

Jeśli zamierzasz to zrobić w czystym CSS (używając scss), ale masz różne elementy / klasy w tej samej klasie nadrzędnej, możesz użyć tej wersji !!

  &: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});
    }
  }
Juan Sebastian Contreras Aceve
źródło
-1

Nie, nie ma czegoś takiego w CSS. Możesz jednak użyć JavaScript, aby obliczyć liczbę dzieci i zastosować style.

Niet the Dark Absol
źródło
1
@ Lübnah Czy możesz wyjaśnić, dlaczego to nieprawda?
Gabriel Santos