2

I'm attempting to select the first item from a group, however I want to exclude certain items from the selection by class.

e.g. In this example, I attempt to select the first .item that doesn't have the .hide class. The not() works, correctly selecting all but the first item, however following first-of-type doesn't seem to match anything.

To clarify, in this example I'm aiming for:

  • 1st item should remain red
  • 2nd item (The first .item without the .hide class) should be blue
  • 3rd item: Green
  • 4th item: Green
  • 5th item: Red
  • 6th item: Green

.item {
  background-color: #060;
  margin-bottom: 2px;
  text-align: center;
  color: #FFF;
}
.hide {
  background-color: #600;
}
/* The important bit */
.item:not(.hide):first-of-type {
  background-color: #006;
}
<div class="item hide">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item hide">5</div>
<div class="item">6</div>

Am I writing the selector incorrectly? Is there an alternative way to do this?

DBS
  • 9,110
  • 4
  • 35
  • 53
  • "Am I writing the selector incorrectly?" You are, but depending on your situation you may or may not even be able to write a correct selector for this - see http://stackoverflow.com/questions/5545649/can-i-combine-nth-child-or-nth-of-type-with-an-arbitrary-selector – BoltClock Mar 10 '16 at 17:37
  • The fifth item should also be red, right? Since it has the `.hide` class. – BoltClock Mar 10 '16 at 17:45
  • please post some examples and what should be their expected colours – Fabrizio Calderan Mar 10 '16 at 17:47

2 Answers2

1

As all your items are divs, if they are the only children in their parent then :first-of-type is equivalent to :first-child. See this answer for more details.

Since you can't directly match the first child with a class (or any other sub-selector) you will need to do this another way, using an overriding rule.

The simplest way to do this is to:

  1. Make all items blue.
  2. Make .hide items red (as intended).
  3. Apply the green styles to .item:not(.hide) ~ .item:not(.hide). That is, all items that don't have the .hide class, that follow the first such item.

This accounts for all possible cases with just one assumption: that if the first element doesn't have the .hide class then it should be blue as well:

.item {
  background-color: #006;
  margin-bottom: 2px;
  text-align: center;
  color: #FFF;
}
.hide {
  background-color: #600;
}
.item:not(.hide) ~ .item:not(.hide) {
  background-color: #060;
}
section {
  float: left;
  width: 20%;
  margin: 20px;
}
<section>
    <div class="item hide">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item hide">5</div>
    <div class="item">6</div>
</section>
<section>
    <div class="item hide">1</div>
    <div class="item hide">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item hide">5</div>
    <div class="item">6</div>
</section>
<section>
    <div class="item">1</div>
    <div class="item hide">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item hide">5</div>
    <div class="item">6</div>
</section>

If the first element may lack the .hide class, but you only want the first .item:not(.hide) after a .hide item to be blue, then it becomes impossible without JavaScript.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
0

The code

This code has the desired effect :

.item {
    background-color: #006;
    margin-bottom: 2px;
    text-align: center;
    color: #FFF;
}

.hide {
    background-color: #600;
}

.item:not(.hide) ~ .item:not(.hide) {
    background-color: #060;
}
<div class="item hide">1</div>
<div class="item hide">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item hide">5</div>
<div class="item">6</div>

(see also this Fiddle)

John Slegers
  • 45,213
  • 22
  • 199
  • 169
  • Apologies I didn't make myself clear, but there may be multiple `.hide` items and I only want to affect the first instance of this. – DBS Mar 10 '16 at 17:42
  • @DBS : Check out my updated code. Does it now match your criteria? – John Slegers Mar 10 '16 at 17:44
  • Perfect, I couldn't get my head around a way to do that. Thanks! (I'll accept the answer as soon as It lets me) – DBS Mar 10 '16 at 17:48