ฉันสามารถรวม: nth-child () หรือ: nth-of-type () กับตัวเลือกโดยพลการได้หรือไม่?


117

มีวิธีเลือกลูกที่ n ทุกตัวที่ตรงกับ (หรือไม่ตรง) กับตัวเลือกโดยพลการหรือไม่? ตัวอย่างเช่นฉันต้องการเลือกทุกแถวตารางคี่ แต่อยู่ในส่วนย่อยของแถว:

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>

แต่:nth-child()ก็ดูเหมือนว่าจะนับทุกtrองค์ประกอบโดยไม่คำนึงถึงหรือไม่ว่าพวกเขากำลังของ "แถว" ชั้นดังนั้นผมจึงจบลงด้วยหนึ่งแม้ "แถว" องค์ประกอบแทนของทั้งสองฉันกำลังมองหา :nth-of-type()สิ่งเดียวกันที่เกิดขึ้นกับ

ใครช่วยอธิบายว่าทำไม?

คำตอบ:


144

นี่เป็นปัญหาทั่วไปที่เกิดขึ้นเนื่องจากความเข้าใจผิดเกี่ยวกับวิธีการ:nth-child()และการ:nth-of-type()ทำงาน แต่น่าเสียดายที่มีอยู่ในปัจจุบันไม่มีการแก้ปัญหาเลือกตามเป็นยังเพราะ Selectors ไม่ได้ให้วิธีการเพื่อให้ตรงกับเด็กที่ n ที่ตรงกับตัวเลือกพลขึ้นอยู่กับรูปแบบเช่นเลขคี่, เลขหรือเป็นan+bที่และa != 1 b != 0สิ่งนี้ครอบคลุมมากกว่าตัวเลือกคลาสเท่านั้นไปจนถึงตัวเลือกแอตทริบิวต์การปฏิเสธและการรวมกันของตัวเลือกแบบง่าย

:nth-child()หลอกชั้นนับองค์ประกอบในหมู่ทั้งหมดของพี่น้องของพวกเขาอยู่ภายใต้การปกครองเดียวกัน ไม่นับเฉพาะพี่น้องที่ตรงกับตัวเลือกที่เหลือ ในทำนองเดียวกัน:nth-of-type()คลาสหลอกจะนับพี่น้องที่แชร์ประเภทองค์ประกอบเดียวกันซึ่งอ้างถึงชื่อแท็กใน HTML ไม่ใช่ส่วนที่เหลือของตัวเลือก

นอกจากนี้ยังหมายความว่าหากลูกทั้งหมดของพ่อแม่เดียวกันเป็นประเภทองค์ประกอบเดียวกันตัวอย่างเช่นในกรณีของเนื้อตารางที่มีลูกคนเดียวเป็นtrองค์ประกอบหรือองค์ประกอบรายการที่มีลูกคนเดียวเท่านั้นที่เป็นliองค์ประกอบ:nth-child()และ:nth-of-type()จะทำงานเหมือนกันกล่าวคือ สำหรับค่าของทุกan+b, :nth-child(an+b)และ:nth-of-type(an+b)จะตรงกับชุดเดียวกันขององค์ประกอบ

ในความเป็นจริงตัวเลือกอย่างง่ายทั้งหมดในตัวเลือกสารประกอบที่กำหนดรวมถึงคลาสหลอกเช่น:nth-child()และ:not()ทำงานเป็นอิสระจากกันแทนที่จะมองไปที่ชุดย่อยขององค์ประกอบที่จับคู่โดยส่วนที่เหลือของตัวเลือก

นอกจากนี้ยังบอกเป็นนัยว่าไม่มีความคิดของลำดับระหว่างตัวเลือกอย่างง่ายภายในตัวเลือกสารประกอบ1 แต่ละตัวซึ่งหมายความว่าตัวอย่างเช่นตัวเลือกสองตัวต่อไปนี้เทียบเท่ากัน:

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

แปลเป็นภาษาอังกฤษทั้งคู่หมายถึง:

เลือกtrองค์ประกอบใด ๆที่ตรงกับเงื่อนไขอิสระทั้งหมดต่อไปนี้:

  • เป็นลูกที่มีเลขคี่ของพ่อแม่
  • มันมีคลาส "row"; และ
  • มันเป็นลูกหลานของtableองค์ประกอบที่มีคลาส "myClass"

(คุณจะสังเกตเห็นการใช้รายการที่ไม่เรียงลำดับที่นี่เพียงเพื่อขับรถกลับบ้าน)

เนื่องจากขณะนี้ยังไม่มีโซลูชัน CSS ที่แท้จริงคุณจะต้องใช้สคริปต์เพื่อกรององค์ประกอบและใช้สไตล์หรือชื่อคลาสเพิ่มเติมตามนั้น ตัวอย่างเช่นต่อไปนี้เป็นวิธีแก้ปัญหาทั่วไปโดยใช้ jQuery (สมมติว่ามีกลุ่มแถวเดียวที่เติมtrองค์ประกอบภายในตาราง):

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

ด้วย CSS ที่สอดคล้องกัน:

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

หากคุณใช้เครื่องมือทดสอบอัตโนมัติเช่น Selenium หรือการประมวลผล HTML ด้วยเครื่องมือเช่น lxml เครื่องมือเหล่านี้จำนวนมากอนุญาตให้ใช้ XPath เป็นทางเลือก:

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

วิธีแก้ปัญหาอื่น ๆ ที่ใช้เทคโนโลยีที่แตกต่างกันถือเป็นแนวทางปฏิบัติสำหรับผู้อ่าน นี่เป็นเพียงตัวอย่างสั้น ๆ ที่จัดทำขึ้นเพื่อเป็นภาพประกอบ


สิ่งที่คุ้มค่ามีข้อเสนอสำหรับส่วนขยายของ:nth-child()สัญกรณ์ที่จะเพิ่มไปยังตัวเลือกระดับ 4 เพื่อวัตถุประสงค์เฉพาะในการเลือกลูกที่ n ทุกตัวที่ตรงกับตัวเลือกที่กำหนด 2

ตัวเลือกที่จะกรองการจับคู่ถูกจัดให้เป็นอาร์กิวเมนต์:nth-child()อีกครั้งเนื่องจากวิธีที่ตัวเลือกทำงานเป็นอิสระจากกันในลำดับตามที่กำหนดโดยไวยากรณ์ตัวเลือกที่มีอยู่ ดังนั้นในกรณีของคุณจะมีลักษณะดังนี้:

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

(ผู้อ่านที่ชาญฉลาดจะทราบทันทีว่าสิ่งนี้ควรเป็น:nth-child(odd of tr.row)แทนเนื่องจากตัวเลือกที่เรียบง่ายtrและ:nth-child()ทำงานเป็นอิสระจากกันเช่นกันนี่เป็นหนึ่งในปัญหาเกี่ยวกับคลาสหลอกที่ใช้งานได้ซึ่งยอมรับตัวเลือกซึ่งเป็นเวิร์ม ไม่เปิดตรงกลางของคำตอบนี้ แต่ฉันจะใช้สมมติฐานว่าไซต์ส่วนใหญ่จะไม่มีองค์ประกอบอื่นใดนอกจากtrองค์ประกอบที่เป็นพี่น้องของกันและกันในเนื้อหาตารางซึ่งจะทำให้ตัวเลือกใดตัวเลือกหนึ่งเทียบเท่ากันได้)

แน่นอนว่าเป็นข้อเสนอใหม่เอี่ยมในข้อกำหนดใหม่ล่าสุดอาจจะไม่เห็นการนำไปใช้จนกว่าจะถึงเวลาอีกไม่กี่ปีข้างหน้า ในระหว่างนี้คุณจะต้องใช้สคริปต์ดังที่กล่าวมาข้างต้น


1 หากคุณระบุประเภทหรือตัวเลือกสากลต้องมาก่อน อย่างไรก็ตามสิ่งนี้ไม่ได้เปลี่ยนแปลงวิธีการทำงานของตัวเลือกโดยพื้นฐาน มันไม่มีอะไรมากไปกว่าการเล่นโวหาร

2 สิ่งนี้ถูกเสนอในตอนแรก:nth-match()เนื่องจากยังคงนับองค์ประกอบที่สัมพันธ์กับพี่น้องเท่านั้นและไม่รวมถึงองค์ประกอบอื่น ๆ ที่ตรงกับตัวเลือกที่กำหนดตั้งแต่ปี 2014 ได้ถูกนำกลับมาใช้ใหม่เป็นส่วนขยายที่มีอยู่:nth-child()แทน


3
"(คุณจะสังเกตเห็นการใช้รายการที่ไม่มีการเรียงลำดับของฉันที่นี่เพียงเพื่อขับรถกลับบ้าน)" ฉันหวังว่าจะมีคนจำนวนมากขึ้นที่พิจารณาเกี่ยวกับการใช้กระสุนที่มีคำสั่งและไม่มีการเรียงลำดับ ขอบคุณสำหรับคำตอบ.
The Red Pea

1
@ ถั่วแดง: หนึ่งในสัตว์เลี้ยง HTML ที่ใหญ่ที่สุดของฉัน: "เรียงลำดับจากสูงสุด / ต่ำสุดไปต่ำสุด / สูงสุด:" ตามด้วยรายการที่ไม่เรียงลำดับ ฉันหมายถึงมาจริงจัง?
BoltClock

6

ไม่จริง ..

อ้างจากเอกสาร

:nth-childหลอกชั้นตรงกับองค์ประกอบที่มี + B-1 พี่น้องก่อนที่มันจะอยู่ในต้นไม้เอกสารสำหรับการกำหนดค่าบวกหรือศูนย์สำหรับ n และมีองค์ประกอบของผู้ปกครอง

เป็นตัวเลือกของตัวเองและไม่รวมกับคลาส ในกฎของคุณมีเพียงเพื่อตอบสนองตัวเลือกทั้งสองในเวลาเดียวกันดังนั้นจึงจะแสดง:nth-child(even)แถวของตารางหากพวกเขามี.rowคลาสด้วย


0

nth-of-typeทำงานตามดัชนีขององค์ประกอบประเภทเดียวกัน แต่nth-childทำงานตามดัชนีเท่านั้นไม่ว่าองค์ประกอบพี่น้องจะเป็นประเภทใด

ตัวอย่างเช่น

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

สมมติว่าใน html ด้านบนเราต้องการซ่อนองค์ประกอบทั้งหมดที่มีคลาสพักผ่อน

ในกรณีนี้nth-childและnth-of-typeจะทำงานเหมือนกับองค์ประกอบทั้งหมดเป็นประเภทเดียวกันที่<div>ควรจะเป็น css

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

หรือ

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

ตอนนี้คุณต้องสงสัยว่าอะไรคือความแตกต่างระหว่างnth-childและnth-of-typeนี่คือความแตกต่าง

สมมติว่า html คือ

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

ใน html ด้านบนประเภทของ.restองค์ประกอบแตกต่างจาก.restย่อหน้าและอื่น ๆ เป็น div ดังนั้นในกรณีนี้หากคุณใช้nth-childคุณต้องเขียนแบบนี้

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

แต่ถ้าคุณใช้ css ที่nอาจเป็นได้

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

ในฐานะที่เป็นประเภทของ.restองค์ประกอบ<p>ดังนั้นนี่nth-of-typeคือการตรวจสอบชนิดของ.restแล้วเขาใช้ CSS ในวันที่ 1, 2, 3, 4, 5 <p>องค์ประกอบของ


<tr>แท็กมีประโยชน์อย่างไร
Alexis Wilke

0

คุณอาจสามารถทำได้ด้วย xpath บางอย่างเช่น//tr[contains(@class, 'row') and position() mod 2 = 0]อาจใช้งานได้ มีคำถามอื่น ๆ เพิ่มเติมเกี่ยวกับรายละเอียดวิธีจับคู่ชั้นเรียนให้แม่นยำยิ่งขึ้น


0

นี่คือคำตอบของคุณ

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

คำถามทั้งหมดเกี่ยวกับการใช้ลูกที่ n และการข้ามแท็กที่ซ่อนอยู่ดูเหมือนว่าจะเปลี่ยนเส้นทางเป็น dupes ของคำถามนี้ดังนั้นฉันจะปล่อยไว้ที่นี่ ฉันเจอบล็อกนี้https://blog.blackbam.at/2015/04/09/css-nth-child-selector-ignore-hidden-element/ที่ใช้วิธีการ css ที่ชาญฉลาดเพื่อทำให้ nth-child ไม่สนใจองค์ประกอบที่ซ่อนอยู่ ดังต่อไปนี้:

CSS ต่อไปนี้จะเพิ่มระยะขอบให้กับองค์ประกอบที่มองเห็นได้ทุกวินาทีไม่ว่าองค์ประกอบใดจะมีคลาส 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;
}

หวังว่าจะช่วยให้ใครบางคนที่กำลังติดตามเส้นทางการหลอกลวงสำหรับคำถามที่ไม่สนใจเกี่ยวกับองค์ประกอบที่ซ่อนอยู่!


1
ฉันต้องการเพิ่มคะแนน แต่ต้องมีการสาธิตที่ใช้งานได้
Moob

ความทรงจำของฉันคือสิ่งนี้ไม่ได้แข็งแกร่งอย่างที่เห็นในตอนแรกตอนนี้ฉันจะไปกับความคิดเห็นที่ได้รับการโหวตสูงสุดซึ่งเป็นไปไม่ได้
IrishDubGuy

0

หากคุณมีคลาสแม่เดียวกันสำหรับตัวเลือกทั้งหมดคุณจะใช้คลาสนั้นdocument.querySelector("main .box-value:nth-child(3) select.priorityOption"); เพราะในกรณีนั้นdocument.querySelector("main .box-value select.priorityOption:nth-child(3)");ไม่ทำงาน ขอบคุณ

<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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.