Tôi có thể kết hợp: nth-child () hoặc: nth-of-type () với một bộ chọn tùy ý không?


117

Có cách nào để chọn mọi con thứ n khớp (hoặc không khớp) với một bộ chọn tùy ý không? Ví dụ: tôi muốn chọn mọi hàng trong bảng lẻ, nhưng trong một tập hợp con của các hàng:

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>

Nhưng :nth-child()dường như chỉ đếm tất cả các trphần tử bất kể chúng có thuộc lớp "hàng" hay không, vì vậy tôi kết thúc với một phần tử "hàng" chẵn thay vì hai phần tử tôi đang tìm. Điều tương tự cũng xảy ra với :nth-of-type().

Ai đó có thể giải thích tại sao?

Câu trả lời:


144

Đây là một vấn đề rất phổ biến phát sinh do sự hiểu lầm về cách thức :nth-child():nth-of-type()công việc. Thật không may, hiện tại vẫn chưa có giải pháp dựa trên bộ chọn vì Bộ chọn không cung cấp cách đối sánh con thứ n khớp với bộ chọn tùy ý dựa trên một mẫu như số lẻ, số chẵn hoặc bất kỳ an+bđâu a != 1b != 0. Điều này mở rộng ra ngoài chỉ các bộ chọn lớp, cho các bộ chọn thuộc tính, phủ định và các kết hợp phức tạp hơn của các bộ chọn đơn giản.

Lớp :nth-child()giả đếm các phần tử trong số tất cả anh chị em của chúng dưới cùng một cha mẹ. Nó không chỉ tính các anh chị em phù hợp với phần còn lại của bộ chọn. Tương tự, lớp :nth-of-type()giả đếm các anh chị em chia sẻ cùng một loại phần tử, tham chiếu đến tên thẻ trong HTML chứ không phải phần còn lại của bộ chọn.

Điều này cũng có nghĩa là nếu tất cả các phần tử con của cùng một cha mẹ đều thuộc cùng một loại phần tử, ví dụ trong trường hợp nội dung bảng có trphần tử con duy nhất là phần tử hoặc một phần tử danh sách có phần tử con duy nhất là liphần tử, thì:nth-child():nth-of-type()sẽ hoạt động giống nhau, tức là cho mỗi giá trị của an+b, :nth-child(an+b):nth-of-type(an+b)sẽ phù hợp với cùng một tập hợp của các yếu tố.

Trên thực tế, tất cả các bộ chọn đơn giản trong một bộ chọn ghép nhất định, bao gồm các lớp giả như :nth-child():not() , hoạt động độc lập với nhau, thay vì xem xét tập hợp con các phần tử được khớp với phần còn lại của bộ chọn.

Điều này cũng ngụ ý rằng không có khái niệm thứ tự giữa các bộ chọn đơn giản trong mỗi bộ chọn phức hợp riêng lẻ 1 , có nghĩa là hai bộ chọn sau đây là tương đương nhau:

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

Được dịch sang tiếng Anh, cả hai đều có nghĩa là:

Chọn bất kỳ tr phần tử nào phù hợp với tất cả các điều kiện độc lập sau:

  • nó là một con số lẻ của cha mẹ nó;
  • nó có lớp "hàng"; và
  • nó là con của một tablephần tử có lớp "myClass".

(bạn sẽ nhận thấy việc tôi sử dụng một danh sách không có thứ tự ở đây, chỉ để lái xe về nhà)

Vì hiện tại không có giải pháp CSS thuần túy, bạn sẽ phải sử dụng tập lệnh để lọc các phần tử và áp dụng các kiểu hoặc tên lớp bổ sung cho phù hợp. Ví dụ: sau đây là một cách giải quyết phổ biến sử dụng jQuery (giả sử chỉ có một nhóm hàng được điền trcác phần tử trong bảng):

$('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');
});

Với CSS tương ứng:

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

Nếu bạn đang sử dụng các công cụ kiểm tra tự động như Selenium hoặc xử lý HTML bằng các công cụ như lxml, thì nhiều công cụ trong số này cho phép XPath thay thế:

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

Các giải pháp khác sử dụng các công nghệ khác nhau được để lại như một bài tập cho người đọc; đây chỉ là một ví dụ ngắn gọn, có nguồn gốc để minh họa.


Đối với những gì nó đáng giá, có một đề xuất mở rộng :nth-child()ký hiệu để được thêm vào Bộ chọn cấp 4 với mục đích cụ thể là chọn mọi con thứ n phù hợp với một bộ chọn nhất định. 2

Bộ chọn để lọc các kết quả phù hợp được cung cấp như một đối số :nth-child(), một lần nữa do cách các bộ chọn hoạt động độc lập với nhau theo một trình tự như được quy định bởi cú pháp bộ chọn hiện có. Vì vậy, trong trường hợp của bạn, nó sẽ giống như sau:

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

(Một độc giả thông minh sẽ lưu ý ngay rằng điều này nên được :nth-child(odd of tr.row)thay thế, vì các bộ chọn đơn giản tr:nth-child()hoạt động độc lập với nhau. Đây là một trong những vấn đề với các lớp giả chức năng chấp nhận bộ chọn, một lon sâu tôi muốn chứ không phải mở ở giữa câu trả lời này. Thay vào đó, tôi sẽ đi đến giả định rằng hầu hết các trang web sẽ không có bất kỳ yếu tố nào khác ngoàitr các phần tử là anh chị em của nhau trong nội dung bảng, điều này sẽ làm cho một trong hai tùy chọn tương đương về mặt chức năng.)

Tất nhiên, là một đề xuất hoàn toàn mới trong một đặc điểm kỹ thuật hoàn toàn mới, điều này có thể sẽ không được triển khai cho đến khi bắt đầu vài năm. Trong thời gian chờ đợi, bạn sẽ phải sử dụng một script, như trên.


1 Nếu bạn chỉ định một loại hoặc bộ chọn đa năng, nó phải đến trước. Tuy nhiên, điều này không làm thay đổi cách thức hoạt động cơ bản của bộ chọn; nó không gì khác hơn là một câu cú pháp.

2 Điều này ban đầu được đề xuất :nth-match(), tuy nhiên vì nó vẫn chỉ tính một phần tử liên quan đến anh chị em của nó, chứ không phải cho mọi phần tử khác khớp với bộ chọn đã cho, kể từ năm 2014, nó đã được thay thế như một phần mở rộng cho phần tử hiện có :nth-child().


3
"(bạn sẽ nhận thấy việc tôi sử dụng một danh sách không có thứ tự ở đây, chỉ để lái điểm về nhà)" Tôi ước rằng nhiều người hơn đã cố ý về việc sử dụng đạn có thứ tự so với không có thứ tự. Cảm ơn bạn vì câu trả lời.
The Red Pea

1
@The Red Pea: Một trong những kẻ trộm thú cưng HTML lớn nhất của tôi: "Theo thứ tự từ cao nhất / thấp nhất đến thấp nhất / cao nhất:" theo sau là một danh sách không có thứ tự. Tôi có nghĩa là đi vào, nghiêm túc?
BoltClock

6

Không hẳn ..

trích dẫn từ tài liệu

Lớp :nth-childgiả khớp với một phần tử có + b-1 anh chị em trước nó trong cây tài liệu , cho một giá trị dương hoặc 0 cho trước cho n và có một phần tử mẹ.

Nó là một bộ chọn của riêng nó và không kết hợp với các lớp. Trong quy tắc của bạn, nó chỉ phải thỏa mãn cả hai bộ chọn cùng một lúc, vì vậy nó sẽ hiển thị các :nth-child(even)hàng của bảng nếu chúng cũng có .rowlớp.


0

nth-of-typehoạt động theo chỉ mục cùng loại của phần tử nhưng nth-childchỉ hoạt động theo chỉ mục bất kể kiểu phần tử anh chị em là gì.

Ví dụ

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

Giả sử trong html trên, chúng ta muốn ẩn tất cả các phần tử có lớp nghỉ.

Trong trường hợp này nth-childnth-of-typesẽ hoạt động giống hệt nhau vì tất cả các phần tử đều có cùng kiểu <div>nên css nên

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

HOẶC LÀ

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

Bây giờ bạn phải tự hỏi sự khác biệt giữa nth-childnth-of-typevì vậy đây là sự khác biệt

Giả sử html là

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

Trong html trên, kiểu .restphần tử khác với những phần tử khác .restlà đoạn văn và những phần tử khác là div nên trong trường hợp này nếu sử dụng nth-childbạn phải viết như thế này

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

nhưng nếu bạn sử dụng css kiểu thứ n có thể là

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

Vì loại .restphần tử là <p>vì vậy ở đây nth-of-typelà phát hiện loại của .restvà sau đó anh ta áp dụng css trên phần tử thứ 1, 2, 3, 4, 5 của <p>.


Điều đó hữu ích như thế nào đối với <tr>các thẻ?
Alexis Wilke

0

Bạn có thể làm điều đó với xpath. một cái gì đó giống như //tr[contains(@class, 'row') and position() mod 2 = 0]có thể hoạt động. Có những câu hỏi SO khác mở rộng về chi tiết cách đối sánh các lớp chính xác hơn.


0

Đây là câu trả lời của bạn

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

0

Tất cả các câu hỏi xung quanh việc sử dụng nth-child và bỏ qua các thẻ ẩn dường như đang chuyển hướng dưới dạng lừa đảo của câu hỏi này nên tôi sẽ để điều này ở đây. Tôi đã xem blog này https://blog.blackbam.at/2015/04/09/css-nth-child-selector-ignore-hidden-element/ sử dụng phương pháp css thông minh để làm cho nth-child bỏ qua các yếu tố ẩn, như sau:

CSS sau đây thêm quyền lề cho mỗi phần tử hiển thị thứ hai bất kể phần tử nào có lớp 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;
}

Hy vọng điều đó sẽ giúp ích cho những ai đang theo dấu vết dupe cho các câu hỏi bỏ qua các yếu tố ẩn!


1
Tôi muốn ủng hộ điều này nhưng nó cần một bản demo hoạt động.
Moob

Hồi ức của tôi là điều này không thực sự mạnh mẽ như ban đầu - bây giờ tôi đi với bình luận được bình chọn nhiều nhất, điều này là không thể.
IrishDubGuy

0

NẾU bạn có cùng một lớp cha cho tất cả bộ chọn, Sau đó, bạn sử dụng lớp đó document.querySelector("main .box-value:nth-child(3) select.priorityOption"); Bởi vì trong trường hợp đó document.querySelector("main .box-value select.priorityOption:nth-child(3)");Không hoạt động. Cảm ơn bạn

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.