9

I'm looking for a way to combine two css selectors. In my case, ':not' and ':first-of-type'. This is my code:

<div id="holder">
  <div class="image mobileOnly">...</div>
  <div class="image">...</div>
  <div class="image">...</div>
  <div class="image">...</div>
  <!-- ... more images ... -->
</div>

I'd like to select the first div.image that's doesn't contain the 'mobileOnly' class.

I tried the following combinations (in different orders):

#holder .image:not(.mobileOnly):first-of-type {
  border: 5px solid #0a85d4;
}

#holder .image:not(.mobileOnly) :first-of-type {
  border: 5px solid #0a85d4;
}

Is this possible at all?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
sanderbee
  • 694
  • 7
  • 24
  • What is your testing configuration (browser / version) ? – enguerranws Dec 21 '15 at 10:19
  • Last version of firefox, Compass 0.12.6 – sanderbee Dec 21 '15 at 10:23
  • Can you provide the compiled version of this code (just in case) ? – enguerranws Dec 21 '15 at 10:25
  • It works check [this](https://jsfiddle.net/alireza_safian/em18f1Lc/). – Alex Dec 21 '15 at 10:27
  • @enguerranws, please see my edit – sanderbee Dec 21 '15 at 10:28
  • @alirezasafian, the example didn't work i think. If the mobileOnly class is set, the second (non-containing mobiliOnly class) must be selected. – sanderbee Dec 21 '15 at 10:33
  • Now, I understand what you want. – Alex Dec 21 '15 at 10:36
  • 2
    @sanderbee Check [this](https://jsfiddle.net/alireza_safian/em18f1Lc/2/). – Alex Dec 21 '15 at 10:40
  • If you don't even know what CSS is necessary to get the result you're after, you have a CSS problem, not a Sass problem. Only post the *compiled CSS* when you have a CSS problem. – cimmanon Dec 21 '15 at 12:15
  • @cimmanon I reopened this question because I don't think that this is a duplicate of the other question (the title is similar, but the actual question and respective answers differ imo) – Danield Dec 21 '15 at 13:21
  • @Danield How is it not a duplicate? The answers here are working around the fact that there is no :first-of-class() selector, which is what the OP actually needs here instead of :first-of-type(). That doesn't make it not a duplicate, and no one actually explained why the OP's logic is wrong. – cimmanon Dec 21 '15 at 13:29
  • @cimmanon hmm, I agree that the root of the issue is that there's no nth-class() selector, however the application needed in both questions is quite different. Also, the question here is certainly doable using CSS whereas in the other question it isn't (at least using general markup) If you think that this still constitutes a duplicate then feel free to revert it to one. :) – Danield Dec 21 '15 at 13:55
  • @Danield I can't vote again. If the OP has multiple .mobileOnly elements or .mobileOnly is not guaranteed to be the first element, **there is no solution** and we're right back to the question I closed this as a duplicate of. – cimmanon Dec 21 '15 at 14:00
  • @cimmanon - Are you sure? I think that the [answer](http://stackoverflow.com/a/34395983/703717) that I provided will work in the above scenarios – Danield Dec 21 '15 at 14:04

2 Answers2

8

This is a tricky question : I don't think there's a simple way to achieve that :)

As far as I understand : you try to select the first .image element, as long as it's not a .mobileOnly element ?

#holder .image:first-child {
  border: 5px solid #0a85d4;
}
#holder .image.mobileOnly:first-child {
  border: none;
}
#holder .image.mobileOnly:first-child + .image {
  border: 5px solid #0a85d4;
}

Live example : http://codepen.io/enguerranws/pen/wMWzBr

Let's explain this : you were trying to select the first child of type .image, which as class .onlyMobile > this couldn't work, because in the case you need, .image wasn't the first child of its type.

Legionar
  • 7,472
  • 2
  • 41
  • 70
enguerranws
  • 8,087
  • 8
  • 49
  • 97
  • Wonderfull! Tried it and it works like charm! Thanks for the explanation. – sanderbee Dec 21 '15 at 10:42
  • You're welcome. The thing is, :first-of-type can't be actually read as "first of this type in the matched set of elements (of that class)" but "first children which has this class". – enguerranws Dec 21 '15 at 10:44
3

If you want to select the first image which doesn't have the mobileOnly class then I would go about it like this:

Set the border on all the images which don't have the the mobileOnly class.

 #holder .image:not(.mobileOnly) {
      border: 5px solid #0a85d4;
 }

Now, at this stage there are still images - after that first one which we are after - that still have the border, so....remove them!

#holder .image:not(.mobileOnly) ~ .image {
  border: none;
}

Codepen Demo

The advantage of this approach is that it will work even if the first multiple elements have the mobileOnly class - it will still style the first image without the mobileOnly class. (demo)

Danield
  • 121,619
  • 37
  • 226
  • 255