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.


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:


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.


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 */
}

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.


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 ...


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

-1

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


1
@ Lübnah Czy możesz wyjaśnić, dlaczego to nieprawda?
Gabriel Santos
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.