9

I've got a project wherein I have no control whatsoever over the markup. I'm looking for a way to select every instance of 'class2' that immediately follows an instance of 'class1'. The following strategy works, but in some cases there are over 20 instances of 'class2' in a row and I'd prefer to avoid that huge mess in my code.

.class1 + .class2, .class1 + .class2 + .class2, .class1 + .class2 + .class2 + .class2, .class1 + .class2 + .class2 + .class2 + .class2, .class1 + .class2 + .class2 + .class2 + .class2 + .class2 // etc. { // Applied Styles } 

...to style the following

<div class="class1"></div> <div class="class2">Style Me!</div> <div class="class2">Style Me!</div> <div class="class2">Style Me!</div> <div class="class2">Style Me!</div> <p>Blah blah blah</p> <div class="class2">DO NOT STYLE ME</div> <div class="class2">DO NOT STYLE ME EITHER</div> 
11
  • Your example makes it look as though this will work just fine: .class1 .class2 {/*styles*/}; Commented Jan 18, 2013 at 21:43
  • That would select a child, not the sibling. Commented Jan 18, 2013 at 21:44
  • @Jason That would only work if class2 was a child of class1 Commented Jan 18, 2013 at 21:44
  • @mookamafoob the example above suggests that class2 is a child of class1 in every case. Commented Jan 18, 2013 at 21:46
  • @Jason You must be thinking of the child combinator > where + is siblings, not parent/child Commented Jan 18, 2013 at 21:47

4 Answers 4

4

Here's a stab in the dark using the new :not selector @spudley suggested. It looks like it has okay support: http://caniuse.com/#search=%3Anot. I hope the syntax is right. Edits welcome.

And most of this was taken from @mookamafoob's solution. I didn't submit an edit in case @mookamafoob was averse to using the :not selector prematurely.

http://jsbin.com/umivas/6/edit

.class1 ~ .class2 + .class2 { color: red; } .class1 + .class2 { color: red; } .class1 ~ *:not(.class2) ~ .class2 { color: inherit; } 

Edit: Sorry for the lack of explanation. The last part attempts to select any element that is a sibling of .class1 that doesn't have .class2 and resets all subsequent siblings with .class2 back to their original state. This could be kind of insane depending on how many styles you're applying.

Sign up to request clarification or add additional context in comments.

4 Comments

@mookamafoob Wouldn't have even come close to an answer without yours >_<
Nice job to @spudley and mooka for coming up with all the ideas that led to a workable solution. Excellent question btw — really worked the brain :)
For the record, the :not() selector is just as new as the ~ combinator - both were introduced in Selectors 3. It just happens, miraculously, that IE7 and IE8 support ~. And yes, the syntax is correct; the only way to accomplish this is by overriding as you've shown :)
@BoltClock Thank you for that. It looks like I have some catching up to do on the new selectors :D
3

My suggestion would be to simply set the style for .class1 ~ .class2, and then override it back to the previous value for p ~ .class2.

It's not a perfect solution, because the second selector there can't know what it's overriding back to; you just have to set it to what you expect the defaults should be. But it should be workable.

Another idea I had was to use the CSS not selector.

With that, you can switch to the easier ~ to select the group of all the relevant class2 elements, but use not and ~ to filter out the ones which follow the <p> tag.

eg:

.class1 ~ :not(p) ~ .class2 

Unfortunately, I don't think this idea will work as shown; the use of the ~ here makes for some combinations we don't want that will be selected regardless of the not. It may be possible to come up with a not selector that will work, but I haven't managed to devise it in the time I've spent trying now.

Comments

3

The general sibling combinator might get what you need. It would look like this:

.class1 ~ .class2 { /* Styles */ } 

You can find more info on it here.

Here is an example as well http://jsbin.com/arorij/1/edit

EDIT

This may work for your case, using two rules together like so:

.class1 ~ .class2 + .class2 { color: red; } .class1 + .class2 { color: red; } 

5 Comments

This selects every instance of 'class2' whether it immediately follows 'class1' or whether it follows with other elements in between. There are many other instances of 'class2' elsewhere on the page, but I only want to select the ones that immediately follow 'class1'.
@AndyMangold Updated with another example that I think will work for your scenario.
Nearly! Sometimes there are other pairs of adjacent "class2"s though: jsbin.com/umivas/3/edit
@mookamafoob the latest example stops working if there is another <div class="class2">DO NOT STYLE ME</div> added to the end of the html
Heh this is why we need a full code example from the beginning. :P
0

Maybe you need to flip the logic around? Can you write a rule for a .class2 that follows a .class1 or a .class2 that follows a .class2?

.class1 + .class2, .class2 + .class2 { ... } 

That rule would not apply to that last div in your example since it follows neither.

1 Comment

That's what @mookamafoob proposed, but sometimes there are other pairs or triplets of the 'class2' further down the page.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.