Dapatkah saya menggabungkan: nth-child () atau: nth-of-type () dengan pemilih arbitrer?

117

Adakah cara untuk memilih setiap anak ke n yang cocok (atau tidak cocok) dengan pemilih arbitrer ? Misalnya, saya ingin memilih setiap baris tabel ganjil, tetapi dalam subset baris:

table.myClass tr.row:nth-child(odd) {
  ...
}
<table class="myClass">
  <tr>
    <td>Row
  <tr class="row"> <!-- I want this -->
    <td>Row
  <tr class="row">
    <td>Row
  <tr class="row"> <!-- And this -->
    <td>Row
</table>

Tapi :nth-child()sepertinya menghitung semua trelemen terlepas dari apakah mereka dari kelas "baris" atau tidak, jadi saya berakhir dengan satu elemen "baris" genap dan bukan dua yang saya cari. Hal yang sama terjadi dengan :nth-of-type().

Adakah yang bisa menjelaskan mengapa?

atanamir
sumber

Jawaban:

144

Ini adalah masalah yang sangat umum yang muncul karena kesalahpahaman tentang bagaimana :nth-child()dan :nth-of-type()bekerja. Sayangnya, saat ini belum ada solusi berbasis pemilih karena Pemilih tidak menyediakan cara untuk mencocokkan turunan ke-n yang cocok dengan pemilih arbitrer berdasarkan pola seperti ganjil, genap, atau di an+bmana pun a != 1dan b != 0. Ini melampaui hanya pemilih kelas, untuk atribut selektor, negasi, dan kombinasi yang lebih kompleks dari penyeleksi sederhana.

Kelas :nth-child()pseudo menghitung elemen di antara semua saudara kandungnya di bawah induk yang sama. Itu tidak hanya menghitung saudara kandung yang cocok dengan pemilih lainnya. Demikian pula, :nth-of-type()pseudo-class menghitung saudara kandung yang berbagi jenis elemen yang sama, yang merujuk ke nama tag dalam HTML, dan bukan pemilih lainnya.

Ini juga berarti bahwa jika semua anak dari orang tua yang sama memiliki tipe elemen yang sama, misalnya dalam kasus badan tabel yang satu-satunya anak adalah trelemen atau elemen daftar yang hanya anak-anak adalah lielemen, maka :nth-child()dan :nth-of-type()akan berperilaku identik, yaitu untuk setiap nilai an+b, :nth-child(an+b)dan :nth-of-type(an+b)akan cocok dengan kumpulan elemen yang sama.

Faktanya, semua pemilih sederhana dalam pemilih gabungan tertentu, termasuk kelas-semu seperti :nth-child()dan :not(), bekerja secara independen satu sama lain, daripada melihat subset elemen yang cocok dengan selektor lainnya.

Ini juga menyiratkan bahwa tidak ada gagasan tentang urutan di antara pemilih sederhana dalam setiap pemilih gabungan 1 , yang berarti, misalnya, dua pemilih berikut ini setara:

table.myClass tr.row:nth-child(odd)
table.myClass tr:nth-child(odd).row

Diterjemahkan ke dalam bahasa Inggris, keduanya berarti:

Pilih trelemen apa pun yang cocok dengan semua kondisi independen berikut:

  • itu adalah anak ganjil dari induknya;
  • itu memiliki kelas "baris"; dan
  • itu adalah turunan dari tableelemen yang memiliki kelas "myClass".

(Anda akan melihat saya menggunakan daftar tidak berurutan di sini, hanya untuk mengarahkan intinya)

Karena saat ini tidak ada solusi CSS murni, Anda harus menggunakan skrip untuk memfilter elemen dan menerapkan gaya atau nama kelas tambahan yang sesuai. Misalnya, berikut ini adalah solusi umum menggunakan jQuery (dengan asumsi hanya ada satu grup baris yang diisi dengan trelemen di dalam tabel):

$('table.myClass').each(function() {
  // Note that, confusingly, jQuery's filter pseudos are 0-indexed
  // while CSS :nth-child() is 1-indexed
  $('tr.row:even').addClass('odd');
});

Dengan CSS yang sesuai:

table.myClass tr.row.odd {
  ...
}

Jika Anda menggunakan alat pengujian otomatis seperti Selenium atau memproses HTML dengan alat seperti lxml, banyak dari alat ini mengizinkan XPath sebagai alternatif:

//table[contains(concat(' ', @class, ' '), ' myClass ')]//tr[contains(concat(' ', @class, ' '), ' row ')][position() mod 2)=1]

Solusi lain yang menggunakan teknologi berbeda dibiarkan sebagai latihan bagi pembaca; ini hanyalah contoh singkat yang dibuat-buat untuk ilustrasi.


Untuk apa nilainya, ada proposal untuk ekstensi pada :nth-child()notasi yang akan ditambahkan ke Pemilih level 4 untuk tujuan khusus memilih setiap anak ke-n yang cocok dengan pemilih tertentu. 2

Selektor yang digunakan untuk memfilter kecocokan disediakan sebagai argumen :nth-child(), sekali lagi karena cara penyeleksi beroperasi secara independen satu sama lain dalam urutan seperti yang ditentukan oleh sintaks pemilih yang ada. Jadi dalam kasus Anda, akan terlihat seperti ini:

table.myClass tr:nth-child(odd of .row)

(Seorang pembaca yang cerdik akan segera mencatat bahwa ini seharusnya menjadi :nth-child(odd of tr.row)gantinya, karena penyeleksi sederhana trdan :nth-child()beroperasi secara independen satu sama lain juga. Ini adalah salah satu masalah dengan kelas-semu fungsional yang menerima penyeleksi, sekaleng cacing saya agak tidak terbuka di tengah jawaban ini. Sebagai gantinya saya akan pergi dengan asumsi bahwa sebagian besar situs tidak akan memiliki elemen lain selain trelemen sebagai saudara satu sama lain dalam badan tabel, yang akan membuat salah satu opsi setara secara fungsional.)

Tentu saja, sebagai proposal baru dalam spesifikasi baru, ini mungkin tidak akan diterapkan hingga beberapa tahun ke depan. Sementara itu, Anda harus tetap menggunakan skrip, seperti di atas.


1 Jika Anda menentukan tipe atau pemilih universal, itu harus diutamakan. Namun, ini tidak mengubah cara kerja penyeleksi pada dasarnya; itu tidak lebih dari sebuah permainan kata-kata sintaksis.

2 Ini pada awalnya diusulkan sebagai :nth-match(), namun karena masih menghitung elemen relatif hanya untuk saudara kandungnya, dan tidak untuk setiap elemen lain yang cocok dengan pemilih yang diberikan, sejak 2014 telah digunakan kembali sebagai perpanjangan dari yang sudah ada :nth-child().

BoltClock
sumber
3
"(Anda akan melihat saya menggunakan daftar tidak berurutan di sini, hanya untuk mengarahkan tujuan ke rumah)" Saya berharap lebih banyak orang yang dengan sengaja menggunakan peluru yang dipesan vs tidak berurutan. Terima kasih atas jawaban Anda.
The Red Pea
1
@ The Red Pea: Salah satu pertanyaan HTML terbesar saya: "Diurutkan dari yang tertinggi / terendah ke terendah / tertinggi:" diikuti dengan daftar yang tidak diurutkan. Maksudku ayolah, serius?
BoltClock
6

Tidak juga..

kutipan dari dokumen

The :nth-childpseudo-class cocok dengan elemen yang memiliki + b-1 saudara sebelum di pohon dokumen , untuk positif yang diberikan atau nilai nol untuk n, dan memiliki elemen induk.

Ini adalah pemilihnya sendiri dan tidak digabungkan dengan kelas. Dalam aturan Anda, itu hanya harus memenuhi kedua selektor pada saat yang sama, sehingga akan menampilkan :nth-child(even)baris tabel jika mereka juga kebetulan memiliki .rowkelas.

Gabriele Petrioli
sumber
0

nth-of-typebekerja menurut indeks dari jenis elemen yang sama tetapi nth-childhanya bekerja menurut indeks tidak peduli jenis elemen saudara kandungnya.

Sebagai contoh

<div class="one">...</div>
<div class="two">...</div>
<div class="three">...</div>
<div class="four">...</div>
<div class="five">...</div>
<div class="rest">...</div>
<div class="rest">...</div>
<div class="rest">...</div>
<div class="rest">...</div>
<div class="rest">...</div>

Misalkan di html di atas kita ingin menyembunyikan semua elemen yang memiliki kelas istirahat.

Dalam hal ini nth-childdan nth-of-typeakan bekerja sama persis karena semua elemen memiliki tipe yang sama <div>sehingga css seharusnya

.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
    display:none;
}

ATAU

.rest:nth-of-type(6), .rest:nth-of-type(7), .rest:nth-of-type(8), .rest:nth-of-type(9), .rest:nth-of-type(10){
    display:none;
}

Sekarang Anda pasti bertanya-tanya apa perbedaan antara nth-childdan nth-of-typejadi inilah perbedaannya

Misalkan html-nya adalah

<div class="one">...</div>
<div class="two">...</div>
<div class="three">...</div>
<div class="four">...</div>
<div class="five">...</div>
<p class="rest">...</p>
<p class="rest">...</p>
<p class="rest">...</p>
<p class="rest">...</p>
<p class="rest">...</p>

Pada html diatas jenis .restelemennya berbeda dengan yang lain .restadalah paragraf dan yang lainnya adalah div jadi dalam hal ini jika menggunakan nth-childharus menulis seperti ini

.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
    display:none;
}

tapi jika Anda menggunakan nth-of-type css bisa seperti ini

.rest:nth-of-type(1), .rest:nth-of-type(2), .rest:nth-of-type(3), .rest:nth-of-type(4), .rest:nth-of-type(5){
    display:none;
}

Karena jenis .restelemennya <p>jadi di sini nth-of-typeadalah mendeteksi jenis .restdan kemudian dia menerapkan css pada elemen ke-1, ke-2, ke-3, ke-4, ke-5 <p>.

Gaurav Aggarwal
sumber
Seberapa berguna itu untuk <tr>tag?
Alexis Wilke
0

Anda mungkin dapat melakukannya dengan xpath. sesuatu seperti //tr[contains(@class, 'row') and position() mod 2 = 0]mungkin berhasil. Ada pertanyaan SO lain yang memperluas rincian bagaimana mencocokkan kelas dengan lebih tepat.

the8472
sumber
0

Inilah jawaban Anda

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>TEST</title>

  <style>

    .block {
      background: #fc0;
      margin-bottom: 10px;
      padding: 10px;
    }
    /* .large > .large-item:nth-of-type(n+5) {
      background: #f00;
    } */

    .large-item ~ .large-item ~ .large-item ~ .large-item ~ .large-item {
      background: #f00;
    }

  </style>
</head>
<body>

<h1>Should be the 6th Hello Block that start red</h1>
<div class="small large">
  <div class="block small-item">Hello block 1</div>
  <div class="block small-item large-item">Hello block 2</div>
  <div class="block small-item large-item">Hello block 3</div>
  <div class="block small-item large-item">Hello block 4</div>
  <div class="block small-item large-item">Hello block 5</div>
  <div class="block small-item large-item">Hello block 6</div>
  <div class="block small-item large-item">Hello block 7</div>
  <div class="block small-item large-item">Hello block 8</div>
</div>

</body>
</html>
Pocketninja
sumber
0

Semua pertanyaan seputar penggunaan nth-child dan melewatkan tag tersembunyi tampaknya dialihkan sebagai penipu yang satu ini jadi saya akan meninggalkan ini di sini. Saya menemukan blog ini https://blog.blackbam.at/2015/04/09/css-nth-child-selector-ignore-hidden-element/ yang menggunakan pendekatan css yang cerdas untuk membuat anak-n mengabaikan elemen tersembunyi, sebagai berikut:

CSS berikut menambahkan hak margin ke setiap elemen detik yang terlihat, tidak peduli elemen mana yang memiliki kelas cpw.

.cpw {
    display:none;
}

.video_prewrap {
    margin-right:20px;
}

.video_prewrap:nth-child(2n) {
    margin-right:0;
}

.cpw ~ .video_prewrap:nth-child(2n) {
    margin-right:20px;
}

.cpw ~ .video_prewrap:nth-child(2n-1) {
    margin-right:0;
}

Harapan yang membantu seseorang yang mengikuti jejak penipuan untuk mengabaikan pertanyaan elemen tersembunyi!

IrishDubGuy
sumber
1
Saya ingin memberi suara positif tetapi ini membutuhkan demo yang berfungsi.
Moob
Ingatan saya adalah bahwa ini sebenarnya tidak sekuat yang terlihat pada awalnya - saya sekarang akan memilih komentar dengan suara terbanyak, ini tidak mungkin.
IrishDubGuy
0

JIKA Anda memiliki kelas induk yang sama untuk semua selector, Maka Anda menggunakan kelas itu document.querySelector("main .box-value:nth-child(3) select.priorityOption"); Karena dalam kasus itu document.querySelector("main .box-value select.priorityOption:nth-child(3)");Tidak berfungsi. Terima kasih

<div class="card table">
    <div class="box">
        <div class="box-value">
            <select class="priorityOption">
                <option value="">--</option>
                <option value="">LOREM</option>
                <option value="">LOREM</option>
            </select>
        </div>

        <div class="box-value">
            <select class="priorityOption">
                <option value="">--</option>
                <option value="">LOREM</option>
                <option value="">LOREM</option>
            </select>
        </div>

        <div class="box-value">
            <select class="priorityOption">
                <option value="">--</option>
                <option value="">LOREM</option>
                <option value="">LOREM</option>
            </select>
        </div>
    </div>
</div>
Jatin Aggarwal
sumber