9

I'm trying to target a class element (appearing more than once in the DOM) by its index or iteration, strictly using CSS.

I know of several different ways of achieving this: I could toss the element(s) in an array and retrieve a specific index of said element (Javascript). I could label the element I'm trying to target with an #ID. I could refine the targeted element by specifying an attribute (.element[href="link"]). The pseudo-class :first-child and :last-child only target the children of that (parent) element (Duh!).

Example: I have a .class appearing 5 times within my DOM and I want to affect the CSS properties of the 3rd iteration of that .class element.

I wish there was a pseudo-class of .element:index-3. There's probably something out there that let's you do just that.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Justin Ward
  • 825
  • 1
  • 7
  • 14
  • 1
    I found a really good list of all the variations you can target an element by. I knew about 90% of them already, but there's some definite eye-openers. [link](http://princexml.com/doc/6.0/selectors/) – Justin Ward Oct 27 '12 at 23:37
  • you should post this as an answer. `div.class:nth-of-type(3)` should perfectly do the trick. – Morgan Wilde Oct 27 '12 at 23:39
  • Hmmm. I saw that listed on the site I linked, so I tried'er out. Apparently it only effects the text of the element targeted. – Justin Ward Oct 28 '12 at 00:39

3 Answers3

4

If I understand you correctly, you want to style the element with the content "Me!" in this example:

<body>
  <p>Not me.</p>
  <p class="me">Not me.</p>
  <div><p class="me">Not me.</p></div>
  <p class="me">Me!</p>
  <div><div><p class="me">Not me.</p></div></div>
  <p class="me">Not me.</p>
</body>

This should be possible In some cases (see below) it is possible with the pseudo-class :nth-of-type:

.me:nth-of-type(3) {color:red;}

As ScottS noted in the comments, this is only possible if all classes are on the same element type (e.g. p).

unor
  • 92,415
  • 26
  • 211
  • 360
  • 4
    This solution fails: `nth-of-type` does not actually look at and count the class, but the _type_ of element. So `.me:nth-of-type(3)` in your example is only targeting the correct `p` because it is the 3rd `p` element directly under the `div` _and_ it has a `.me` class. [This fiddle](http://jsfiddle.net/N9btF/3/) shows that introducing another `p` without the `.me` class causes the selector to fail. – ScottS Oct 28 '12 at 01:21
  • @ScottS: Ah, wasn't aware of that. Thanks for the info. I updated it in the answer. – unor Oct 28 '12 at 02:21
  • Sorry guys. Nothing you've mentioned is new to me, nor is it the solution I was after. I'll try and reword the question: Consider this...(I'll make reference to an array, but only figuratively, not syntactically) Let's say I have an array of 5 objects. I would like to select the 3rd object in the array, regardless of any sibling related to said object. I just want to target the 3rd instance of the object. Not by type, not by attr, not by child, etc. – Justin Ward Oct 28 '12 at 04:34
  • @JustinWard--an "array" implies _consecutive_ objects of like type in order. Is that really what your DOM looks like? Are these like `li` elements all sitting next to each other in the DOM? Or do you seek the 3rd instance whether or not it is consecutive to other instances of the same object? – ScottS Oct 28 '12 at 11:58
  • I said exactly what I meant. Five separate
    elements each part of the same class. I want to target one of those divs by its index number. Not the first or last. Not referencing its children.
    – Justin Ward Oct 28 '12 at 23:31
  • It's easier to append an id to the div in question and target it that way. – Justin Ward Oct 28 '12 at 23:34
  • Further to @ScottS's comment, it is therefore meaningless to qualify `:nth-of-type()` with a class selector if you're not trying to filter only by that class. Also see [this answer](http://stackoverflow.com/questions/2717480/css-selector-for-first-element-with-class/8539107#8539107) for a much more thorough description. – BoltClock Oct 31 '12 at 18:46
2

I have a .class appearing 5 times within my DOM and I want to affect the CSS properties of the 3rd iteration of that .class element.

I'm reading this as "target third element that uses .class across the entire DOM", e.g.:

<h1 class="class">...</h1>                    #1
<div>
  <ul class="class">                          #2
    <li>...</li>
    <li class="class">...</li>                #3, target this one!
    <li>...</li>
  </ul>
  <div class="class">...</div>                #4
</div>
<p class="class">...</div>                    #5

Any :nth- pseudo-class notation represents an element qualified by the number of siblings matching a certain criteria (:nth-child(an+b) has an+b-1 siblings before it etc.).

CSS specification (including selectors level 4 draft) does not provide means of qualifying elements by index outside of sibling context (i.e. only individual nodes can be traversed, not the entire DOM tree). There is a performance reason behind this (traversing DOM is tough, imagine async content update, this is not how rendering engines work); but also something like :nth-element-ever(3) would be a very, very arbitrary criteria and would be better targeted by introduction of another class that means exactly what it does, preferably during code generation.

Oleg
  • 24,465
  • 8
  • 61
  • 91
  • Yeah. I didn't think it was possible. I was just curious...it seems like there are some pretty educated minds on these forums, so I figured I'd give it a shot. I have no problem appending an ID to the element and targeting it more precisely that way. I was just trying to find an alternate method. – Justin Ward Oct 28 '12 at 05:01
0

If the elements are not placed as adjacent siblings, or at least in the same "scope" (container element), there's no way for you to find out existence, iteration, or actually nothing about "related" elements.

Your best shot is either use a very ugly solution, based on the assumption the elements are siblings, which might look like so: li.class:first-child + li + li { color: black; } to find the 3rd iteration,

or just use some JS to calculate occurance of an instace and insert it as a special class, like "gimme-css-here".

Devon Ville
  • 2,001
  • 2
  • 19
  • 32