Bisakah CSS mendeteksi jumlah anak yang dimiliki suatu elemen?

304

Saya mungkin menjawab pertanyaan saya sendiri, tetapi saya sangat ingin tahu.

Saya tahu bahwa CSS dapat memilih masing-masing anak dari orang tua, tetapi adakah dukungan untuk menata anak-anak dari sebuah wadah, jika orang tuanya memiliki jumlah anak tertentu.

sebagai contoh

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

Saya tahu kedengarannya aneh, tetapi manajer saya meminta saya untuk memeriksanya, belum menemukan apa pun pada saya jadi saya memutuskan untuk beralih ke SO sebelum mengakhiri pencarian.

Brodie
sumber
2
Kuantitas Permintaan SCSS Mixin: codepen.io/jakob-e/pen/wgGpeP
Jakob E

Jawaban:

695

Klarifikasi:

Karena ungkapan sebelumnya dalam pertanyaan awal, beberapa warga negara SO telah mengajukan kekhawatiran bahwa jawaban ini bisa menyesatkan. Perhatikan bahwa, di CSS3, gaya tidak dapat diterapkan ke simpul orangtua berdasarkan jumlah anak yang dimilikinya. Namun, gaya dapat diterapkan pada simpul anak-anak berdasarkan jumlah saudara kandung yang mereka miliki.


Jawaban asli:

Luar biasa, ini sekarang mungkin murni di 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%;
}

Caranya adalah dengan memilih anak pertama saat itu juga anak ke-n dari anak terakhir. Ini secara efektif memilih berdasarkan jumlah saudara kandung.

Penghargaan untuk teknik ini jatuh ke André Luís (ditemukan) & Lea Verou (disempurnakan).

Apakah Anda tidak suka CSS3? 😄

Contoh CodePen:

Sumber:

Matthemattics
sumber
7
Sangat berguna. Saya menulis mixin SASS yang menggunakan teknik ini: codepen.io/anon/pen/pJeLdE?editors=110
SimpleJ
1
@IanSteffy Saya baru saja menguji ini di Chrome 45.0.2454.85 (64-bit) dan berfungsi dengan baik ...?
Matthemattics
2
Jika bekerja di codepen tetapi tidak dengan proyek saya maka itu pasti salah saya. Salahku. Jawaban ini benar! Benar, kataku!
Ian S
3
Mungkin lebih baik untuk menambahkan mengapa ini bekerja, untuk orang-orang yang tidak terbiasa dengan beberapa penyeleksi semu (seperti saya dulu sampai sekarang;). Apa yang terjadi di sini adalah bahwa ini memilih anak yang pada saat yang sama anak x dari awal / atas dan anak y dari akhir. Dan jadi ini hanya memilih sesuatu jika ada x + y anak-anak.
Legolas
7
Perhatikan bahwa alih-alih :first-child:nth-last-child(1)Anda juga dapat menggunakan :only-child.
Adam Reis
40

Tidak. Yah, tidak juga. Ada beberapa penyeleksi yang bisa membuat Anda agak dekat, tetapi mungkin tidak akan berfungsi dalam contoh Anda dan tidak memiliki kompatibilitas browser terbaik.

:only-child

Ini :only-childadalah salah satu dari sedikit penyeleksi penghitungan sejati dalam arti bahwa itu hanya diterapkan ketika ada satu anak dari elemen induk. Menggunakan contoh ideal Anda, itu bertindak sepertichildren(1) mungkin.

:nth-child

Itu :nth-child pemilih mungkin benar-benar mendapatkan Anda di mana Anda ingin pergi tergantung pada apa yang Anda benar-benar ingin lakukan. Jika Anda ingin menata semua elemen jika ada 8 anak, Anda kurang beruntung. Namun, jika Anda ingin menerapkan gaya ke elemen ke-8 dan yang lebih baru, coba ini:

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

Sayangnya, ini mungkin bukan solusi yang Anda cari. Pada akhirnya, Anda mungkin perlu menggunakan beberapa Javascript wizardry untuk menerapkan gaya berdasarkan hitungan - bahkan jika Anda akan menggunakan salah satu dari ini, Anda harus melihat keras kompatibilitas browser sebelum menggunakan murni Solusi CSS.

W3 CSS3 Spec pada pseudo-class

EDIT Saya membaca pertanyaan Anda sedikit berbeda - ada beberapa cara lain untuk gaya orang tua , bukan anak-anak. Biarkan saya melempar beberapa penyeleksi lain ke jalan Anda:

:empty dan :not

Elemen gaya ini yang tidak memiliki anak. Tidak terlalu berguna sendiri, tetapi ketika dipasangkan dengan :notpemilih, Anda hanya dapat menata elemen yang memiliki anak:

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

Anda tidak dapat menghitung berapa banyak anak yang tersedia dengan CSS murni di sini, tetapi itu adalah pemilih lain yang menarik yang memungkinkan Anda melakukan hal-hal keren.

derekerdmann
sumber
Perlu dicatat bahwa pertanyaan asli telah diedit, menjadikan "Tidak" agak awal menyesatkan (hanya fyi 😛)
Matthemattics
18

CATATAN: Solusi ini akan mengembalikan anak-anak set dengan panjang tertentu, bukan elemen induk seperti yang Anda minta. Semoga bermanfaat.

Andre Luis datang dengan metode: http://lea.verou.me/2011/01/styling-children-based-on-their-number-with-css3/ Sayangnya, itu hanya bekerja di IE9 dan di atas.

Pada dasarnya, Anda menggabungkan: nth-child () dengan kelas pseudo lain yang berhubungan dengan posisi elemen. Pendekatan ini memungkinkan Anda menentukan elemen dari set elemen dengan panjang tertentu .

Misalnya :nth-child(1):nth-last-child(3)cocok dengan elemen pertama dalam set sementara juga menjadi elemen ke-3 dari akhir set. Ini melakukan dua hal: menjamin bahwa himpunan hanya memiliki tiga elemen dan bahwa kita memiliki yang pertama dari ketiganya. Untuk menentukan elemen kedua dari set elemen tiga, kami akan menggunakan :nth-child(2):nth-last-child(2).


Contoh 1 - Pilih semua elemen daftar jika set memiliki tiga elemen:

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

Contoh 1 alternatif dari Lea Verou:

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


Contoh 2 - target elemen terakhir dari himpunan dengan tiga elemen daftar:

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

Alternatif contoh 2:

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


Contoh 3 - elemen target kedua set dengan empat elemen daftar:

li:nth-child(2):nth-last-child(3) {
    /* I'm the second of four */
}
ifugu
sumber
1
lagi, ini jumlah saudara kandung, bukan anak
TMS
@TMS lihat edit jawaban yang diterima - pertanyaan OP dengan canggung diungkapkan
ifugu
Pendekatan ini sangat cocok untuk ketika setiap elemen harus ditata berbeda berdasarkan posisinya dalam daftar, misalnya untuk mendapatkan transformasi melingkar: li:nth-child(3):nth-last-child(1) { transform: rotate(120deg); } li:nth-child(2):nth-last-child(2) { transform: rotate(240deg); }dan seterusnya ...
Greg Smith
11

Mengatasi solusi Matt, saya menggunakan implementasi Kompas / SCSS berikut.

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

Ini memungkinkan Anda untuk dengan cepat memperluas jumlah item.

mwtidd
sumber
4
Alih-alih ini, Anda dapat dengan mudah menggunakan Flexbox ...
Michał Miszczyszyn
6

ya kita bisa melakukan ini menggunakan nth-child seperti itu

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

Ini akan membuat div anak ke-8 dan seterusnya menjadi merah. Semoga ini membantu...

Juga, jika seseorang pernah mengatakan "hei, itu tidak bisa dilakukan dengan gaya menggunakan css, gunakan JS !!!" ragu mereka segera. CSS sangat fleksibel saat ini

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

Dalam contoh 7 anak pertama berwarna biru, kemudian 8 dan seterusnya berwarna merah ...

AlanFoster
sumber
1
Mungkin menambahkan catatan tentang kurangnya dukungan yang disayangkan ?
benesch
2
Saya tidak berpikir inilah yang diminta Brodie - ini akan memberi gaya pada anak - anak setelah jumlah tertentu, tetapi tidak dapat memilih elemen leluhur / mengandung berdasarkan jumlah anak-anaknya.
Ben Hull
Ini sebenarnya adalah beberapa informasi yang cukup bagus, terima kasih alan tetapi lebah benar, saya mencoba untuk mengatakan "jika sebuah elemen memiliki anak sebanyak ini dengan gaya ini" Jika saya tidak salah metode Anda akan mendesain anak ke-8, tetapi 7 pertama akan kesepian dan telanjang.
Brodie
@ primatologi - Satu-satunya browser yang tidak mendukung n-child adalah IE <9. Semua yang lain telah mendukungnya dua versi kembali atau lebih.
Rob
-1 Ini tidak akan membuat div child red, ini akan membuat div red berdasarkan jumlah dalam saudara - saudaranya ! Tidak terkait dengan anak div dengan cara apa pun!
TMS
5

Jika Anda akan melakukannya dalam CSS murni (menggunakan scss) tetapi Anda memiliki elemen / kelas yang berbeda di dalam kelas induk yang sama Anda dapat menggunakan versi ini !!

  &: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
sumber
-1

Tidak, tidak ada yang seperti ini di CSS. Namun, Anda dapat menggunakan JavaScript untuk menghitung jumlah anak dan menerapkan gaya.

Niet the Dark Absol
sumber
1
@ Lübnah Bisakah Anda menjelaskan mengapa itu tidak benar?
Gabriel Santos