Let's take these three selectors, sorted from the highest specificity to the lowest:
.special-section p { }
.weird-font { }
p { }
Many CSS gurus recommend against nesting like in the first selector .special-section p, because its specificity is high enough that you can't override it with a simple class like .weird-font. I would like to find a way to still achieve nesting like in .special-section p, but without increasing specificity. Something like this:
.weird-font { }
.special-section p /* with hack to decrease specificity */ { }
p { }
Use case:
It's pretty safe to apply defaults for typography and such document-wide using simple selectors like p. However, I would like to change those defaults for a particular section, similar to .special-section p, without having to use hacks to increase the specificity of selectors like .weird-font. I would rather use a hack to decrease the specificity of .special-section p than use a hack to increase the specificity of .weird-font. Is there a way to do this?
You can't decrease the specificity, but you can add an even more specific selector for the exception.
.weird-font, /* Normal weird font */
.special-section p.weird-font /* Override for special section */
{ }
But as you can see, it's a sliding scale. So those gurus are probably right. If you would remove .special-section p, and instead give those P's their own selector .special-section-para or something, then you won't have this problem.
But personally, I don't mind having to add an exception like the one above now and then. I think the whole specifity thing is there for that purpose, and if you need a more specific selector to style something, to me that seems the right thing to do.
A commonly heard solution is to use !important. The problem with !important is that there is only one level of override. If you make a more specific selector, you can override it again with a still even more specific selector. After using !important, you're out of options. More importantly, using !important may interfere with special style sheets that a user may have for increased readability. For that reason I never use !important in a situation like this.
But then again, I don't consider myself a CSS guru. ;)
These days, in 2018, this is getting close to possible.
First of all, CSS4 will have a way that allows you to create more specific selectors without increasing specificity:
:where(.special-section) p {
color: red;
}
This will set the paragraph color inside .special-section to red, but with a specificity of 001 (i.e. the same specificity that a plain p selector would have).
The spec still calls this special pseudo-class :something(), but chances are it's going to be called :where(). (Side note: I really want this to be known as the "honey badger selector").
But that's still in the future.
However, there is actually a way to achieve this today, if you don't have to support IE anymore (or are happy with less-than-perfect fallbacks), and that is by using custom properties a.k.a. CSS variables.
So you want this:
.special-section p { color: red; }
.weird-font { color: magenta; }
p { color: green; }
but with the first part having a specificity that's lower than any selector with a class in it. You can do it like this:
.special-section p { --low-specificity-color: red; }
.weird-font { color: magenta; }
p { color: var(--low-specificity-color, green); }
If you run the below snippet in a modern browser, you should notice that the second paragraph is red, because it's in a special section, but the third paragraph is magenta, because it's .weird-font -- even though .weird-font has 010 specificity and .special-section p has 011.
.special-section p { --low-specificity-color: red; }
.weird-font { color: magenta; }
p { color: var(--low-specificity-color, green); }
<p>This is a paragraph.</p>
<section class="special-section">
<p>This is a paragraph inside a special section.</p>
<p class="weird-font">This is a paragraph with a weird font inside a special section.</p>
</section>
<p class="weird-font">This is a paragraph with a weird font.</p>
<div class="weird-font">This is a div with a weird font.</div>
This works because while the --low-specificity-color is changed with 011 specificity, it is only applied with a 001 specificity.
As a CSS guru, I bemoan the idea of throwing out everything Selectors has to offer just to avoid specificity issues. That's not to say I don't believe the specificity mechanic is flawed, but surely there are less dramatic workarounds for it.
First off: no, you can't decrease the specificity of a selector. Selectors doesn't provide any features with negative specificity levels that would decrease specificity in such a manner. The lowest you can go is *, which has zero specificity (i.e. it does not make a complex selector any more or less specific).
So your only recourse on the selector level is to increase it. Whether you can do this without using hacks depends on your definition of "hack".
The following is what I would consider a hack, because it makes use of a syntactically legal but semantically nonsensical selector like :not(_) that has no obvious purpose but to add a type selector's worth of specificity to a complex selector (which is far from obvious especially to the uninitiated):
.special-section p { }
.weird-font, :not(_).weird-font { }
The following is not what I would consider a hack, because it's something you would do normally anyway. Pretty much the only "issue" with it is that it's an apparent repetition of the lone class selector:
.special-section p { }
.weird-font, .special-section p.weird-font { }
If you consider any sort of extraneous selector for the sake of increasing specificity a hack — which is a perfectly reasonable POV, make no mistake — then the next best thing that isn't a hack is !important.
Personally, I would choose a specificity hack. !important has, ahem, important repercussions that don't come with a specificity hack — remember that !important and specificity have different semantics. For example, you cannot override an !important declaration with an inline style or JavaScript unless they are marked important as well.1
1 In fact, this was my response to Lea Verou when she had a discussion on Twitter some time ago regarding specificity hacks versus !important.
I like to be as specific as is currently necessary. I do like to leave room for future CSS changes, so don't go as specific as possible for the sake of it, such as:
.great-grandfather .grandfather .father .child { }
I will if I have to of course. But taking the example above, if I wanted to override the .child for a particular element that uses this class which has styling which might be like this:
.child {
color: black;
}
I'd go one parent above to override it, if possible:
.father .child {
color: white;
}
Further down the line, if an element on a particular page uses the .child class and in this case I need to override both the .father .child, I'll go one more level of specificity:
.grandfather .father .child {
color: red;
}
Doing it this ensures you don't need to use !important... Which I avoid like the plague as much as possible!
Related
I need to increase class specifity of a given class selector.
Example:
.test {
color: #fff;
}
At the moment i need to type .test.test to increase specifity.
Is there another approach to solve this, like a function increase() or some other way of increasing it without appending the same classname?
If you're using SCSS, then the simplest way (besides forcing it with !important) is to include a parent selector so that it has a higher specificity:
.parent {
.test {
color: #fff;
}
}
Another method is to target the element as well (if it's always the same type of element). This would also give it a higher specificity.
div.test {
color: #fff;
}
If all else fails, you can try moving the code block lower in the SCSS file, since the last selector in the document will win if they have the same specificity. Or, give it the good ol' !important at the end.
.test {
color: #fff !important;
}
there are multiple approaches:
- You can use !important, so that you do not need to repeat class twice. but this is a bad practice.
- Best way - you can place the class code in the last so that even if the specificity is equal, last one will override previous.
- you can use parent selector or tag selector, but that makes code dependent on that parent or tag.
- you can learn more about specificity on https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
In a case like the following, is the performance impact significant?
html
<div class="6u 12u(xsmall)"></div>
css
[class~="6u"] { background-color: red }
/* instead of */
.\36 u { background-color: red }
The advantage is obviously readability.
Edit: I already proposed changing the classes to be eg u6 and not require escaping, but I am asking in the meantime, since I can not change the markup at the moment.
In my CSS, I have this:
b {
color: Red;
}
And in my body:
<b>Hello world!</b>
As a result, I get "Hello world!" text that is red in color.
However, as I add more classes:
.myClass {
color: Blue;
}
.green {
color: Green;
}
And I modify my body:
<b>H<a class="myClass">ell</a><a class="green">o</a> wo<a style="color: Black;">rl</a>d
I will not get the same result as earlier.
Is there a way to strictly set a CSS style? Which means that with the above code I wish to get "Hello world!" text that is red.
Thanks
This is a question of CSS Specificicty
The concept: 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.
Inline styles override external CSS, and class selectors override element level selectors.
The following list of selectors is by increasing specificity:
Universal selectors
Type selectors <--- your b CSS
Class selectors <---- your .xyz CSS
Attributes selectors
Pseudo-classes
ID selectors
Inline style <--- your style=''
If you wish to override specificity, you can use !important after the rule in question, e.g.:
b {
color: Red !important;
}
However, this is not recommended, instead you should write 'better' rules (more specific) to target your HTML as appropriate. This ensures you end up with better structured code, the issue with !important being it can lead to unforeseen circumstances where rules aren't working because you may have forgot you had previously overridden them.
Again, from MDN:
The !important exception
When an !important rule is used on a style declaration, this
declaration overrides any other declaration made in the CSS, wherever
it is in the declaration list. Although, !important has nothing to do
with specificity. Using !important is bad practice because it makes
debugging hard since you break the natural cascading in your
stylesheets.
Some rules of thumb
Never use !important on site-wide css. Only use !important on
page-specific css that overrides site-wide or foreign css (from ExtJs
or YUI for example). Never use !important when you're writing a
plugin/mashup. Always look for a way to use specificity before even
considering !important
With the markup that you provided, no. Otherwise, maybe
The inline style has priority over the stylesheet so part of the text will be black no matter what. You might be able to create a rule that has enough specificity that it will take precendence over any other rules.
b, b .myClass, b .green {
color: red;
}
Though this can get troublesome to maintain. And there is still a chance that a different css rule will get higher precedence later on. I am not completely sure that even specifying all the children with * will do it.
You seem to be asking whether you can set a property (color in the example) on an element in a manner that will not be overridden by settings on inner elements.
You cannot do that with settings on the element itself. But you can set a property on an element and all of its descendants:
b, b * {
color: Red !important;
}
This will override any normal settings for color on inner elements. But it is ineffective against, say, .green { color: Green !important; }. To defeat that, you would need a more specific selector, such as b .green, for your rule—so there is no general way to achieve that (i.e., a way that is independent of the specific markup used inside the element).
This question already has answers here:
What does !important mean in CSS?
(5 answers)
Closed 3 years ago.
How is the CSS attribute property !important read?
Is it really important, exclamation mark important, ...?
Answer: From the answers below, it seems to be read simply important, or bang important.
an "!important" declaration (the delimiter token "!" and keyword
"important" follow the declaration) takes precedence over a normal
declaration.
http://www.w3.org/TR/CSS2/cascade.html#important-rules
Basically, where two style rules are the same... it gives the one marked !important greater importance and will apply those styles.
Example
div{
opacity:0 !important;
}
div.jason{
opacity:1;
}
The first rule would be applied even though the second rule is more specific (one element + one class as opposed to one element)
Note: IE6 ignores !important when you have two of the same property and one of them is important - it'll always apply the last declaration, whether or not it was marked important. **Added from #BoltClock's comment below.
Warning: !important is a hammer that should only be used when absolutely necessary. Almost always, it is better to use more specific selectors to achieve greater specificity and have your styles applied the way you want. !important can make it very difficult for future developers to find and make changes to your code.
One good use case: !important is great for user-defined styles, where a user wants to manipulate Web site pages in specific way in his browser (say make all the backgrounds black and the text yellow). Without having to worry about specificity, the user can add styles to certain elements (like body) and make the styles render.
Just "important" or "bang important." The ! is definitely not a negation in this case.
It's not a tag, it's a keyword.
body { color: red !important; } means, in English, "The text-color of red is important".
In terms of how CSS sees it, it applies more "weight" to that declaration, so it will be (far) more likely to be the applied style.
For an example of this, we can use
p { color: red; }
p.blue { color: blue; }
Now, any p with a class of blue will show blue text, all the others will show red text.
If we change it to this...
p { color: red !important; }
p.blue { color: blue; }
They will all show red text (even if they have a class of blue), as we've given more important to the first selector.
I like to think of it as "NOT important".
p {
color: red !important; /* The rest is NOT important for this CSS property. */
}
Meaning that everything else from that declaration and on is NOT important and should not be taken into account. The idea came from the usage of the "!" character as a boolean NOT in many programming languages. This way the !important makes sense as you read it.
I guess I read the ! as "very".
p { color: red !important }
I read as "Paragraphs have the color red, which is very important.
Is there a way to make an entire CSS Style sheet take precedence over another? I know you can do the !important but can I do that with one line rather than modify all thousand properties on the sheet?
Thanks!
Make sure the stylesheet you want is called last (or a specific style you want is called last). For example, using this:
span { color: red; }
span { color: blue; }
...will turn all text in <span>'s blue. Take a look here.
Rules with identical specificity that come later will overrule previous ones, so if both style sheets contain the identical selectors, you should be able to do this by just loading the one before the other.
If they contain different selectors, like
#navigation h3 { color: red }
and
.mainpage .navmenu h3 { color: blue }
you are likely to get specificity conflicts. The only blanket solution for that is indeed !important (although that is really, really terrible architecturally. Are you sure you need this? Maybe explain why, it's possible somebody is able to come up with a better solution.)
There is, however, no single-line directive to elevate the "importance" of one style sheet over the other.