0

I have a situation in which I load a style with a selector that should be prioritized over another. The situation looks like the one in this fiddle, in which a specific id selector is not being prioritized over another one that uses a class that is under a specific id.

--HTML
<div id="cont">
<p class="hello" id="hello">I wish I was blue</p>
</div>

--CSS
#hello {
    color:blue;
}
#cont .hello {
    color:red;
}

Result is red text

I'm pretty sure this could be possible without using !important - which I really would like to avoid since this will be maintained by designers with no css skills for A/B testing. I want to make a selector for them that they will only edit it's properties.

Edit: To be clear, the #hello selector is injected to the page and I want to change it to one that actually works, but I don't want to change the other selector for that purpose. Of course if I have no choice I will, but it seems reasonable to be that this css is valid as it is and overriding that selector should be possible without modifying it.

Moti Azu
  • 5,392
  • 1
  • 23
  • 32
  • move the `#hello` style down. so it will overwrite without important. – Suresh Ponnukalai Aug 11 '14 at 12:48
  • @SureshPonnukalai http://jsfiddle.net/vkftfj2n/2/ didn't seem to help – Moti Azu Aug 11 '14 at 12:49
  • 2
    @mot: Would it be possible for you to make the `#hello` also as `#cont #hello`? That should solve it. This [CSS Tricks article](http://css-tricks.com/specifics-on-css-specificity/) has more info on selector specificity. – Harry Aug 11 '14 at 12:50
  • You are targeting `.hello` starting with an id, if you just want to target class `.hello` then leave the id out and just do `.hello {}` there are so many ways around this and you just happen to implement the way that it does not work – Huangism Aug 11 '14 at 12:52
  • @Huangism While I know this can be done differently, there are reason for that selector to be the way it is, and it was coded way before I touched it. I don't wish to change it while I have other reasonable solutions. – Moti Azu Aug 11 '14 at 13:04

3 Answers3

2

Simply use the :not selector to exclude the #hello element.

Change the first to:

#cont .hello:not(#hello) {
    color:red;
}

Demo Fiddle

More on :not from MDN

The negation CSS pseudo-class, :not(X), is a functional notation taking a simple selector X as an argument. It matches an element that is not represented by the argument. X must not contain another negation selector, or any pseudo-elements.


Alternatively- per the comments below, you can increase the specificity of the second selector whilst providing variations for various contexts:

#hello, #cont #hello, #hello.hello {
    color:blue;
}

Demo Fiddle

SW4
  • 69,876
  • 20
  • 132
  • 137
  • +1 mate. I really like this option, with the only possible drawback being IE <= 8 support (as usual duh :() – Harry Aug 11 '14 at 12:55
  • I have problem with this solution. I want to change only the #hello selector, because the other one is contained in a website that while I can change it, I would hate to do it because I am injecting the #hello selector into the page under certain circumstances, and the page doesn't need to change for these random needs. I wasn't clear about this is my question, I will edit it now. – Moti Azu Aug 11 '14 at 12:59
1

I suggest you to add another id selector to the first set of CSS rules.

 #cont #hello {
    color:blue;
   }

 #cont .hello {
    color:red;
   }

DEMO http://jsfiddle.net/a_incarnati/53q74jah/

In this case the color was overridden in red because you were using just one id selector #hello and that it's less specific than a selector with 2 ids combined or one id and one class combined, like you have done:

#cont .hello {
    color:blue;
}

One of the things to take into account when writing CSS code, it’s the concept of CSS specificity. Understanding well this concept will avoid you to have to use !important;

As Mozilla Developer Network defines it, specificity is nonetheless:

Specificity is the means by which a browser decides which property values are the most relevant to an element and gets to be applied. Specificity is only based on the matching rules which are composed of selectors of different sorts.

The following list of selectors is by increasing specificity:

  • Universal selectors
  • Type selectors
  • Class selectors
  • Attributes selectors
  • Pseudo-classes
  • ID selectors
  • Inline style

You can measure specificity counting how many selectors are present in a CSS statement.

CSS Specificity can be represented by 4 columns of priority:

inline=1|0|0|0

id=0|1|0|0

class=0|0|1|0

element=0|0|0|1

Left to right, the highest number takes priority.

enter image description here

Alessandro Incarnati
  • 7,018
  • 3
  • 38
  • 54
0

You don't need two different selectors. You can keep one:

.hello {
    color:red;
}
#cont .hello {
    color:blue;
}

http://jsfiddle.net/vkftfj2n/4/

Marion LP
  • 142
  • 5
  • May I understand the downvote? You wish you were blue, and, weren't you on my jsfiddle? – Marion LP Aug 11 '14 at 12:54
  • I'd also like to know the reasoning behind the downvote. Honestly, I think using classes over ID's is great; it gives a set of reusable style rules, and if you really need to change something under a specific scope, that's when you can apply #id .class selector rules. – Morklympious Aug 11 '14 at 12:59
  • I don't know who downvoted. I edited my question to further explain my needs, which this solution doesn't meet. While I agree that using classes over ids in these situation is smarter, I have other considerations in this case. – Moti Azu Aug 11 '14 at 13:08