14

How do I apply specific css styling to every (for the sake of argument) odd element in a set of elements, while taking into account a set of excluded elements?

The issue is replicated here (shown in a codepen):

http://codepen.io/houdmont/pen/VLOBBG

A series of elements which have a class .foo applied:

<a href="#" class="foo">1. Blue</a>
<a href="#" class="foo">2. Green</a>
<a href="#" class="foo">3. Blue</a>
<a href="#" class="foo bar">4. Hidden (blue)</a>
<a href="#" class="foo bar">5. Hidden (blue)</a>
<a href="#" class="foo bar">6. Hidden (blue)</a>
<a href="#" class="foo">7. Green</a>

When the .bar class is applied, the element is hidden.

I'd like the remaining elements with .foo applied to be styled odd/even.

Attempt as follows:

.bar {
    display: none;
}

/**
 * This clearly doesn't work as I'd hoped it would.
 */
.foo:not(.bar):nth-of-type(even) {
    color: green;
}

Ideally, I'd like the seventh element to be green, even though it's an "odd" element, if I were able to exclude the elements with class .bar then it would be the fourth element and therefore considered "even", setting the color to green.

Is this possible with CSS?

Houdmont
  • 1,293
  • 1
  • 12
  • 20

2 Answers2

3

Unfortunately not possible. Previously answered here: https://stackoverflow.com/a/12205844/1590962

CSS is fully declarative; every selector is a simple condition that is true or false independently of any selector part. It's not a procedural language where you take a set and process it, narrowing it down with each step. A selector language with procedural rules would be immune to many kinds of optimisation and would be slower.

So nth-of-type is only about position within an element's parent, and not position in a 'results list so far' because CSS selectors have no such concept. A selector engine could look up the test for nth-of-type before narrowing it with not, as the rules do not interfere with each other.

Community
  • 1
  • 1
cjol
  • 1,485
  • 11
  • 26
  • 1
    Happy to accept that as the answer, thank you. Also found that CSS4 selectors will address this issue: http://www.smashingmagazine.com/2013/01/sneak-peek-future-selectors-level-4/#tree-structural-pseudo-classes-nth-match-nth-last-match – Houdmont Aug 18 '15 at 15:00
  • 1
    If a question was previously answered elsewhere, you should flag the question as a duplicate instead. This saves you the trouble of having to copy the answer over and link back to it. – BoltClock Aug 18 '15 at 15:10
  • I will do that next time! (I couldn't find the flag button earlier...) – cjol Aug 18 '15 at 15:15
0

As Hephistocles said, there isn't any way to do this with only css. On other hand, with javascript it's very simple:

var list = document.getElementsByClassName('foo');
var x=0;
for(i=0;i<list.length; i++){
    if(x%2==1) list[i].style.color='green';
    if(list[i].className.indexOf("bar")==-1) x++;
}