105

How can I select a certain element in a list of elements? I have the following:

<div class="myclass">my text1</div>
<!-- some other code follows -->
<div>
    <p>stuff</p>
</div>
<div>
    <p>more stuff</p>
</div>
<p>
    <span>Hello World</span>
</p>
<div class="myclass">my text2</div>
<!-- some other code follows -->
<div>
    <p>stuff</p>
</div>
<p>
    <span>Hello World</span>
</p>
<input type=""/>
<div class="myclass">my text3</div>
<!-- some other code follows -->
<div>
    <p>stuff</p>
</div>
<footer>The end</footer>

I have the CSS class div.myclass {doing things} that applies to all, obviously, but I also wanted to be able to select the first, second, or third div of class .myclass like this, regardless of where they are in the markup:

div.myclass:first {color:#000;} 
div.myclass:second {color:#FFF;} 
div.myclass:third {color:#006;}

Almost like the jQuery index selection .eq( index ), which is what I am using currently, but I need a no-script alternative.

To be specific, I am looking for pseudo selectors, not things like adding another class or using IDs to make things work.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Tumharyyaaden
  • 2,733
  • 3
  • 19
  • 20
  • 3
    How about the CSS's **[nth-child](http://reference.sitepoint.com/css/pseudoclass-nthchild)**, did you try that....? **Note:** This works in modern browsers only – Sarfraz May 01 '10 at 18:42
  • 4
    That note seems to be synonymous to "No IE". – extraneon May 01 '10 at 18:59
  • 1
    @extraneon: Yup, you got it right :) – Sarfraz May 01 '10 at 19:06
  • 2
    This would not work since there are no uniform parent containers, which is why i wanted to select based on class name occurrence rather. I would have to look at each and every instance and find out the parent tag,id or class in order to select the child. Doing which does not give me uniformity and is difficult to read and would also need to be updated if parent objects/attributes change. – Tumharyyaaden May 01 '10 at 19:36
  • 1
    nth-child is now supported by IE 9+. – awilkinson Oct 20 '15 at 17:18

6 Answers6

89

use nth-child(item number) EX

<div class="parent_class">
    <div class="myclass">my text1</div>
    some other code+containers...

    <div class="myclass">my text2</div>
    some other code+containers...

    <div class="myclass">my text3</div>
    some other code+containers...
</div>
.parent_class:nth-child(1) { };
.parent_class:nth-child(2) { };
.parent_class:nth-child(3) { };

OR

:nth-of-type(item number) same your code

.myclass:nth-of-type(1) { };
.myclass:nth-of-type(2) { };
.myclass:nth-of-type(3) { };
CJ Ramki
  • 2,620
  • 3
  • 25
  • 47
Bdwey
  • 1,813
  • 1
  • 16
  • 18
  • 48
    -1 You (and everyone who upvoted this answer) seem to have misunderstood the "some other code+containers" part. It's not literally that text. It's other *elements*. If you have any other div elements among these ones, your selectors will stop working altogether. – BoltClock Aug 04 '14 at 06:46
  • @BoltClock, your comment initially struck me as misguided...until I investigated further. See my "answer" on this same page that demonstrates the problem that (I think) you were trying to point out. Thank you for your expertise. – Andrew Willems Feb 24 '16 at 21:59
33

You probably finally realized this between posting this question and today, but the very nature of selectors makes it impossible to navigate through hierarchically unrelated HTML elements.

Or, to put it simply, since you said in your comment that

there are no uniform parent containers

... it's just not possible with selectors alone, without modifying the markup in some way as shown by the other answers.

You have to use the jQuery .eq() solution.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
22

This isn't so much an answer as a non-answer, i.e. an example showing why one of the highly voted answers above is actually wrong.

I thought that answer looked good. In fact, it gave me what I was looking for: :nth-of-type which, for my situation, worked. (So, thanks for that, @Bdwey.)

I initially read the comment by @BoltClock (which says that the answer is essentially wrong) and dismissed it, as I had checked my use case, and it worked. Then I realized @BoltClock had a reputation of 300,000+(!) and has a profile where he claims to be a CSS guru. Hmm, I thought, maybe I should look a little closer.

Turns out as follows: div.myclass:nth-of-type(2) does NOT mean "the 2nd instance of div.myclass". Rather, it means "the 2nd instance of div, and it must also have the 'myclass' class". That's an important distinction when there are intervening divs between your div.myclass instances.

It took me some time to get my head around this. So, to help others figure it out more quickly, I've written an example which I believe demonstrates the concept more clearly than a written description: I've hijacked the h1, h2, h3 and h4 elements to essentially be divs. I've put an A class on some of them, grouped them in 3's, and then colored the 1st, 2nd and 3rd instances blue, orange and green using h?.A:nth-of-type(?). (But, if you're reading carefully, you should be asking "the 1st, 2nd and 3rd instances of what?"). I also interjected a dissimilar (i.e. different h level) or similar (i.e. same h level) un-classed element into some of the groups.

Note, in particular, the last grouping of 3. Here, an un-classed h3 element is inserted between the first and second h3.A elements. In this case, no 2nd color (i.e. orange) appears, and the 3rd color (i.e. green) shows up on the 2nd instance of h3.A. This shows that the n in h3.A:nth-of-type(n) is counting the h3s, not the h3.As.

Well, hope that helps. And thanks, @BoltClock.

div {
  margin-bottom: 2em;
  border: red solid 1px;
  background-color: lightyellow;
}

h1,
h2,
h3,
h4 {
  font-size: 12pt;
  margin: 5px;
}

h1.A:nth-of-type(1),
h2.A:nth-of-type(1),
h3.A:nth-of-type(1) {
  background-color: cyan;
}

h1.A:nth-of-type(2),
h2.A:nth-of-type(2),
h3.A:nth-of-type(2) {
  background-color: orange;
}

h1.A:nth-of-type(3),
h2.A:nth-of-type(3),
h3.A:nth-of-type(3) {
  background-color: lightgreen;
}
<div>
  <h1 class="A">h1.A #1</h1>
  <h1 class="A">h1.A #2</h1>
  <h1 class="A">h1.A #3</h1>
</div>

<div>
  <h2 class="A">h2.A #1</h2>
  <h4>this intervening element is a different type, i.e. h4 not h2</h4>
  <h2 class="A">h2.A #2</h2>
  <h2 class="A">h2.A #3</h2>
</div>

<div>
  <h3 class="A">h3.A #1</h3>
  <h3>this intervening element is the same type, i.e. h3, but has no class</h3>
  <h3 class="A">h3.A #2</h3>
  <h3 class="A">h3.A #3</h3>
</div>
Community
  • 1
  • 1
Andrew Willems
  • 11,880
  • 10
  • 53
  • 70
  • 1
    Haha my profile is a little tongue-in-cheek I'll admit... but that's not even the problem with the answer I commented on - the problem is that it takes the "some other code+containers..." text completely literally, when it's obviously referring to other actual intervening elements, which would have interfered with the :nth-child() matches (which, looking at it again, are all written wrongly for a different reason altogether). But as you have discovered, :nth-of-type() is a different beast... – BoltClock Feb 25 '16 at 03:13
  • 1
    Also, more on :nth-child(), :nth-of-type(), and arbitrary selectors in these other answers of mine: http://stackoverflow.com/questions/5545649/can-i-combine-nth-child-or-nth-of-type-with-an-arbitrary-selector/5546296#5546296 http://stackoverflow.com/questions/24657555/what-is-the-difference-between-first-child-and-first-of-type/24657721#24657721 – BoltClock Feb 25 '16 at 03:20
21

Yes, you can do this. For example, to style the td tags that make up the different columns of a table you could do something like this:

table.myClass tr > td:first-child /* First column */
{
  /* some style here */
}
table.myClass tr > td:first-child+td /* Second column */
{
  /* some style here */
}
table.myClass tr > td:first-child+td+td /* Third column */
{
  /* some style here */
}
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
David
  • 283
  • 2
  • 2
11

Perhaps using the "~" selector of CSS?

.myclass {
    background: red;
}

.myclass~.myclass {
    background: yellow;
}

.myclass~.myclass~.myclass {
    background: green;
}

See my example on jsfiddle

Netsi1964
  • 3,244
  • 1
  • 27
  • 17
  • 2
    This only works for sibling elements and not what the OP is asking for (regardless of markup) – Zach Saucier Feb 25 '16 at 03:50
  • 1
    But it was handy in writing a React Jest unit test, where pseudo-selectors don't work. So, thanks, Netsi1964 – eon Feb 25 '19 at 20:49
2

In the future (perhaps) you will be able to use :nth-child(an+b of s)

Actually, browser support for the “of” filter is very limited. Only Safari seems to support the syntax.

https://css-tricks.com/almanac/selectors/n/nth-child/

fred727
  • 2,644
  • 1
  • 20
  • 16