Is there a way to select every nth child that matches (or does not match) an arbitrary selector? For example, I want to select every odd table row, but within a subset of the rows:
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>
But :nth-child() just seems to count all the tr elements regardless of whether or not they're of the "row" class, so I end up with the one even "row" element instead of the two I'm looking for. The same thing happens with :nth-of-type().
Can someone explain why?
This is a very common problem that arises due to a misunderstanding of how :nth-child(An+B) and :nth-of-type() work.
In Selectors Level 3, the :nth-child() pseudo-class counts elements among all of their siblings under the same parent. It does not count only the siblings that match the rest of the selector.
Similarly, the :nth-of-type() pseudo-class counts siblings sharing the same element type, which refers to the tag name in HTML, and not the rest of the selector.
This also means that if all the children of the same parent are of the same element type, for example in the case of a table body whose only children are tr elements or a list element whose only children are li elements, then :nth-child() and :nth-of-type() will behave identically, i.e. for every value of An+B, :nth-child(An+B) and :nth-of-type(An+B) will match the same set of elements.
In fact, all simple selectors in a given compound selector, including pseudo-classes such as :nth-child() and :not(), work independently of one another, rather than looking at the subset of elements that are matched by the rest of the selector.
This also implies that there is no notion of order among simple selectors within each individual compound selector1, which means for example the following two selectors are equivalent:
table.myClass tr.row:nth-child(odd)
table.myClass tr:nth-child(odd).row
Translated to English, they both mean:
Select any tr element that matches all of the following independent conditions:
it is an odd-numbered child of its parent;
it has the class "row"; and
it is a descendant of a table element that has the class "myClass".
(you'll notice my use of an unordered list here, just to drive the point home)
Selectors level 4 seeks to rectify this limitation by allowing :nth-child(An+B of S)2 to accept an arbitrary selector argument S, again due to how selectors operate independently of one another in a compound selector as dictated by the existing selector syntax. So in your case, it would look like this:
table.myClass tr:nth-child(odd of .row)
Of course, being a brand new proposal in a brand new specification, this probably won't see implementation until a few years down the road.
In the meantime, you'll have to use a script to filter elements and apply styles or extra class names accordingly. For example, the following is a common workaround using jQuery (assuming there is only one row group populated with tr elements within the table):
$('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');
});
With the corresponding CSS:
table.myClass tr.row.odd {
...
}
If you're using automated testing tools such as Selenium or scraping HTML with tools like BeautifulSoup, many of these tools allow XPath as an alternative:
//table[contains(concat(' ', #class, ' '), ' myClass ')]//tr[contains(concat(' ', #class, ' '), ' row ')][position() mod 2)=1]
Other solutions using different technologies are left as an exercise to the reader; this is just a brief, contrived example for illustration.
1 If you specify a type or universal selector, it must come first. This does not change how selectors fundamentally work, however; it's nothing more than a syntactic quirk.
2 This was originally proposed as :nth-match(), however because it still counts an element relative only to its siblings, and not to every other element that matches the given selector, it has since as of 2014 been repurposed as an extension to the existing :nth-child() instead.
Not really..
quote from the docs
The :nth-child pseudo-class matches an
element that has an+b-1 siblings
before it in the document tree, for a
given positive or zero value for n,
and has a parent element.
It is a selector of its own and does not combine with classes. In your rule it just has to satisfy both selector at the same time, so it will show the :nth-child(even) table rows if they also happen to have the .row class.
nth-of-type works according to the index of same type of the element but nth-child works only according to index no matter what type of siblings elements are.
For example
<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>
Suppose in above html we want to hide all the elements having rest class.
In this case nth-child and nth-of-type will work exactly same as all the element are of same type that is <div> so css should be
.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
display:none;
}
OR
.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;
}
Now you must be wondering what is the difference between nth-child and nth-of-type so this is the difference
Suppose the html is
<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>
In the above html the type of .rest element is different from others .rest are paragraphs and others are div so in this case if you use nth-child you have to write like this
.rest:nth-child(6), .rest:nth-child(7), .rest:nth-child(8), .rest:nth-child(9), .rest:nth-child(10){
display:none;
}
but if you use nth-of-type css can be this
.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;
}
As type of .rest element is <p> so here nth-of-type is detecting the type of .rest and then he applied css on the 1st, 2nd, 3rd, 4th, 5th element of <p>.
You may be able to do that with xpath. something like //tr[contains(#class, 'row') and position() mod 2 = 0] might work. There are other SO questions expanding on the details how to match classes more precisely.
Here is your answer
<!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>
All of the questions around using nth-child and skipping hidden tags appear to be redirecting as dupes of this one so I will leave this here. I came across this blog https://blog.blackbam.at/2015/04/09/css-nth-child-selector-ignore-hidden-element/ that uses a clever css approach to make nth-child ignore hidden elements, as follows:
The following CSS adds a margin right to every second visible element no matter which element has the cpw class.
.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;
}
Hope that helps someone who is following the dupe trail for the ignore hidden elements questions!
IF you have same parent class for all selector, Then you use that class document.querySelector("main .box-value:nth-child(3) select.priorityOption");
Because in that case document.querySelector("main .box-value select.priorityOption:nth-child(3)"); Not working. Thank You
<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>
Not an answer to "Can someone explain why?" since other answers has explained.
But as one possible solution to your situation, you may use custom tags for the rows and cells, say <tr-row>, <td-row>, then :nth-of-type() should work. Don't forget to set style display: table-row; and display: table-cell; respectively to make them still work like table cells.
I need to verify if a DIV has some text or not inside of it BUT NOT inside its children, eg see this example
<div id='one'>
<div id='two'>Abc</div>
</div>
<div id='three'>xyz
<div id='four'></div>
</div>
If I hover/click element one I want to get false (no text), but if i hover element three I want to get true
i tried using
$('#one').text().trim().length > 0
but it seems to check also any children which is want I do not want to happen
This is already answered here: jquery - get text for element without children text
Also mentions using a plugin to accomplish getting only the text of the element and not child elements here: http://viralpatel.net/blogs/jquery-get-text-element-without-child-element/
This meets your requirements
window.onload=function(){
var two = document.getElementById('two').textContent;
console.log(two.trim()=='');
var three = document.getElementById('three').textContent;
console.log(three.trim()=='');
}
<div id='one'>
<div id='two'>Abc</div>
</div>
<div id='three'>
<div id='four'></div>
</div>
I saw that one can calculate the number of divs by id with the following code:
$('div[id^=d]').length
however I want to calculate the number of divs inside a in specific , example below
<div class="DAD">
<DIV CLASS="The DIV BE TOLD"></DIV>
<DIV CLASS="The DIV BE TOLD"></DIV>
<DIV CLASS="The DIV BE TOLD"></DIV>
<DIV CLASS="The DIV BE TOLD"></DIV>
</DIV>
$('div.DAD div').length would do it.
Or
$('div.DAD div.The.DIV.BE.TOLD').length
jsFiddle example
See: http://api.jquery.com/length/
JQuery allows you to use the syntax of CSS selectors (have a look here):
$('div.DAD div').length
should give the answer you're looking for
I have a problem when hiding/showing certain elements in IE8. If an element with display:inline-block has any child (including nested children) with display:block, then any child of that element has problems when hiding/showing. The page does not redraw correctly, and other elements position do not change to reflect the newly hidden/shown elements.
The minimal markup that shows the problem is below. In the example, when you click 'Clickable element', then the three divs directly below are hidden. However, the Footer Div does not change position - a large gap is left. If you do something to force a page redraw, such as selecting all text on the page, then the footer jumps to the correct position.
Something similar happens when showing the elements. Instead of the footer div being pushed to the bottom, it is overlapped by the newly shown elements.
<div style="display:inline-block">
<div>
<!-- Any number of other HTML elements -->
<div style="display:block">
<div class = "clickable" >Clickable element.</div>
<div class = "toggleable">Hideable element 1.</div>
<div class = "toggleable">Hideable element 2.</div>
<div class = "toggleable">Hideable element 3.</div>
</div>
</div>
</div>
<div>Footer Div</div>
<script type="text/javascript">
$('.clickable').click(function(){
$('.toggleable').toggle();
});
</script>
I've been trying to break this down for a fair while now, and I'm almost certain that I've got the minimal problem down (inline-block element followed by block element, and perform a show/hide on a child element). Has anybody encountered this before - or any suggestions on how to work around this?
This should do the trick. As the answer below states, inline-block isn't supported in older browsers and shows some quirky behaviour in certain versions of IE8. I've remembered this fix from something I did a while back, but I'm sorry, I can't give you a full explanation as to why this is happening. Anyhow, add a float to your main div, and clear your footer and, fingers crossed, it should work.
<div style="display:inline-block;float:left">
<div>
<!-- Any number of other HTML elements -->
<div class="div-2" style="display:block">
<div class = "clickable" >Clickable element.</div>
<div class = "toggleable">Hideable element 1.</div>
<div class = "toggleable">Hideable element 2.</div>
<div class = "toggleable">Hideable element 3.</div>
</div>
</div>
</div>
<div style="clear:left">Footer Div</div>
Seems to be working fine in here... But note that IE8 have some problems rendering jquery, and the css property 'inline-block' is not really supported by old browser versions (ie7, doesn't work, ie8, i'm not sure). Try adding the "zoom:1;" fix to the css of your tags that have the inline-block going on. Hope that helps somehow.
I have a main container <div> which holds 4 or 5 other sub <div>s. The container has a fixed height and a fixed width. What is the best way to position the sub divs so that they are arranged in a top->down then left->right manner?
I've tried floating the sub divs but that just gives me a left->right then top->down order.
Basically I want this
[ sub div 1][sub div 3][sub div 4]
[ sub div 2][ ][sub div 5]
When I mark up the code like this:
<div id="container">
<div class="subdiv">sub div 1...</div>
<div class="subdiv">sub div 2...</div>
<div class="subdiv">sub div 3...</div>
<div class="subdiv">sub div 4...</div>
<div class="subdiv">sub div 5...</div>
</div>
Notice that the sub divs can have variable heights but fixed widths.
Thank you,
To my knowledge, there's no way to do it.
There is some CSS3 that works only on some browsers to support multi-column layout (-moz-column-width, etc...) but I don't know whether it would work with DIVs in the content. And I'm fairly certain it it's not supported in IE7
The way I'd do it would be to break up the content into 3 columns containers
<div id="container">
<div class='column'>
<div class="subdiv">sub div 1...</div>
<div class="subdiv">sub div 2...</div>
</div>
<div class='column'>
<div class="subdiv">sub div 3...</div>
<div class="subdiv">sub div 4...</div>
</div>
<div class='column'>
<div class="subdiv">sub div 5...</div>
</div>
</div>
Use this CSS on the DIVs:
display: inline-block
The only way to do this natively is to use CSS3 columns (as Damp mentioned) but there are some articles on how to achieve a similar effect with JavaScript as seen in this question. That case is actually more complicated than yours.
I'm thinking the best way to do it with JS would be to first split it evenly into column containers as Damp suggested with a best guess. This should help for those with JS disabled. Then us JS to measure heights of the subdivs and move them if the initial guess was off. Assuming you're using a server side language to generate the page, you should be able to split the columns evenly. You can probably even make a good estimation on the split by checking the length of content (assuming its text) as a heuristic for the likely height of the subdiv.