Understanding specificity: achieving desired selector outcomes without using !important [duplicate] - css

This question already has answers here:
How are the points in CSS specificity calculated
(7 answers)
Closed 6 years ago.
I am trying to understand specificity in CSS.
My current understanding is that specificity is very similar to inheritance, but in some way more specifically defined.
Mozilla Specificity Definition:
Specificity is the means by which browsers decide which CSS property values are the most relevant to an element and, therefore, will be applied. Specificity is based on the matching rules which are composed of CSS selectors of different sorts.
The current task is:
Refactor the CSS declarations for .active a and .copyright so that the !important rule can be removed.
CSS:
.main li a {
color: #7ab2c1;
}
.active a {
color: #826c55 !important;
}
.primary p {
font-size: 12px;
}
.copyright {
font-size: 10px !important;
}
And relevant HTML:
<nav class="main">
<ul class="group">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
[...]
<footer class="primary">
<p>Sign up for our newsletter, it's a racket!</p>
<p class="copyright">Copyright © Sven's Snowshoe Emporium. All Rights Reserved.</p>
</footer>
Can anyone guide me through the process of refactoring in such a way that helps me to grasp the fundamental concepts?

A class has a specificity of 10. An element has a specificity of 1.
Therefore, in the first instance:
the .main li a selector has a specificity of 12.
the .active a selector has a specificity of 11
Because they both target the same element, and the former has a higher specificity, the latter loses the battle to style the element.
In the second instance:
the .primary p selector has a specificity of 11.
the .copyright selector has a specificity of 10.
Again, because they both target the same element, and the former has a higher specificity, the latter loses the battle to style the element.
The !important annotation trumps all specificity. Hence, with that applied, .active a and .copyright re-take the elements.
If you want to remove !important, which would be the right thing to do as it's not necessary here, you can instead boost the specificity of the selectors.
An ID has a specificity of 100. So that can quickly move a selector up in priority.
Here are some examples:
.main li a { color: #7ab2c1; } /* previous winner; specificity 12 */
.main .active a { color: #ff0000; } /* added class selector; specificity now 21 */
.primary p { font-size: 12px; } /* previous winner; specificity 11 */
#copyright { font-size: 8px;} /* switched to ID selector; specificity now 100 */
<nav class="main">
<ul class="group">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
<footer class="primary">
<p>Sign up for our newsletter, it's a racket!</p>
<p id="copyright">Copyright © Sven's Snowshoe Emporium.
All Rights Reserved.</p>
</footer>
References:
How do I give a CSS class priority over an id?
CSS Specificity
CSS Specificity: Things You Should Know
Relationship between !important and CSS specificity

You can change .copyright to a lot of things, but one of the following two seems the most logical to me:
.primary .copyright
or
p.copyright
What specificity is supposed to do, is look at an how specific your selector is, and deciding whether that rule should be followed.
CSS inside a media-query is more specific than the exact same CSS outside of it
Ids are more specific than classes
html body section p.special.selected:hover is more specific than p
Etc.
There are a whole bunch of rules that give your selector 'points' with every part. The more points, the more specific. After a lot of practice, you can write over-ruling CSS without even thinking about it.

In this example, you're trying to make the selectors that are setting properties that you wish to override less specific. That way, you won't have as far to go to override them.
Let's take a look at
.main li a {
color: #7ab2c1;
}
.active a {
color: #826c55 !important;
}
.main li a is pretty darn specific: it's selecting all anchor tags within an li within an element with main in its className. How could you make that less specific? Based on your markup,
.main a {
color: #7ab2c1;
}
is less specific, is still applicable, and would be overridden by your .active selector as it has the same specificity (a class + an element). nav a or even plain old a would work as selectors, too, depending on how much (or how little) you want that rule to apply.
Now, let's look at the footer.
.primary p {
font-size: 12px;
}
.copyright {
font-size: 10px !important;
}
How can we make that first selector less specific? What about changing it to
p {
font-size: 12px;
}
Your .copyright selector is more specific and would override it (however, all p elements everywhere will have a default font-size of 12px and that may not be what you want).
We could limit that to the footer:
.primary {
font-size: 12px;
}
That would limit the font-size property to just footer elements and would allow you to override it with the subsequent rule.
In general, you're attempting to refactor based on specificity values to make the things you want to override have the smallest specificity values possible. You do this by using the most general selectors that would apply the rules you want without applying those rules to elements that should not have them.

Basically using html tags as a selector adds a small amount of specificity, using a class adds a medium amount of specificity, using an ID adds a large amount of specificity, and using !important trumps all.
The .main li a selector uses 1 class + 2 html tags while .active a only uses 1 class + 1 html tag. The former has more specificity than the latter, but using !important overrides this and forces the latter style to apply.
To remove the need for !important you either need to a) reduce the amount of specificity in .main li a or b) increase the amount of specificity in .active a. I would recommend option a and changing the selector to .main a. This carries the same amount of specificity as .active a, but due to the cascading nature of CSS, the style that appears last will get applied, no !important needed.
Same principle in the 2nd scenario - .primary p has 1 class + 1 html tag, while .copyright only has 1 class. In this case, I'd go with option b and change the selector to .primary .copyright. 2 classes have more specificity than 1 class + 1 html tag and the style will apply without needing !important.
Final CSS:
.main a {
color: #7ab2c1;
}
.active a {
color: #826c55;
}
.primary p {
font-size: 12px;
}
.primary .copyright {
font-size: 10px;
}

Related

li : hover is not working for list items which have background-color defined [duplicate]

I'd like to understand how CSS selectors work with property collisions. How is one property selected over another one?
div {
background-color: red;
}
div.my_class {
background-color: black;
}
div#my_id {
background-color: blue;
}
body div {
background-color: green;
}
body>div {
background-color: orange;
}
body>div#my_id {
background-color: pink;
}
<div id="my_id" class="my_class">hello</div>
How does selector priority work?
I'll just toss in a link to the CSS 2.1 spec itself, and how browsers are supposed to calculate specificity:
CSS 2.1 Section 6.4.3:
A selector's specificity is calculated as follows:
count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
count the number of ID attributes in the selector (= b)
count the number of other attributes and pseudo-classes in the selector (= c)
count the number of element names and pseudo-elements in the selector (= d)
The specificity is based only on the form of the selector. In particular, a selector of the form "[id=p33]" is counted as an attribute selector (a=0, b=0, c=1, d=0), even if the id attribute is defined as an "ID" in the source document's DTD.
Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.
If the specificities are equal, then CSS 2.1 Section 6.4.1 comes into play:
Finally, sort by order specified: if two declarations have the same weight, origin and specificity, the latter specified wins. Declarations in imported style sheets are considered to be before any declarations in the style sheet itself.
Note that this is talking about when the style is defined, not when it is used. If classes .a and .b have equal specificity, whichever is defined last in the stylesheet(s) wins. <p class="a b">...</p> and <p class="b a">...</p> will be styled identically, based on the definition order of .a and .b.
Element
Class selectors
ID Selectors
Inline styles
!important
In order, 1 is the lowest specificity and 5 is the highest.
https://youtu.be/NqDb9GfMXuo will shown details to demo it.
What you are interested in is specificity.
Firebug is a great tool to help inspect this. But other browsers also have built in tools for inspecting the applied CSS rules.
You can refer the full answer here Mozilla documentation
Start from the most specific:
id selectors > class selectors > type selectors(normal h1, p tag and so on..)
!important always wins, but it is considered a bad practice.See the link above.
The best way is to experiment with it:
<!-- start class vs id -->
<p class="class1" id="id1">.class vs #id: The winner is #id</p>
<!-- upper vs bottom -->
<p id="id2">the very bottom is the winner</p>
<!--most specific is the winner -->
<p id="id3">the most specific</p>
<!--pseudo and target selector -->
<h3>pseudo vs type selector</h3>
<!-- !important is more important! -->
<h1 id="very-specific">HI! I am very important!</h1>
</body>
CSS:
#id1{
color: blue;
}
.class1{
color: red;
}
#id2{
color: yellow;
}
#id2{
color : green;
}
body p#id3{
color :orange;
}
body p{
color : purple;
}
body{
color : black;
}
h3::first-letter {
color: #ff0000;
}
h3{
color: CornflowerBlue ;
}
h1{
color: gray !important;
}
body h1#very-specific{
color: red;
}
Here's a test case.

:not selector is changing the evaluated order of equivalent selectors [duplicate]

This question already has answers here:
What is the most character-efficient way to increase CSS specificity?
(4 answers)
Closed 4 years ago.
I have an issue where I'm working in a rather large CSS code base that makes frequent use of overriding previously defined classes/selectors. As such, it is very sensitive to the order in which they are defined.
Here is a sample of how I need it to work
.grid {
padding:25px;
background-color: red;
}
.grid {
padding:50px;
background-color: green;
}
<li>
<div class="grid">
Test
</div>
</li>
Notice how the second .grid definition overrides the first.
This is what is happening now:
.grid:not(.ui) {
padding:25px;
background-color: red;
}
.grid {
padding:50px;
background-color: green;
}
<li>
<div class="grid">
Test
</div>
</li>
Using the :not pseudo-class hover moves the evaluated priority to after normal class definitions. I need it to be evaluated in the same order as before, but I need the :not selector. Are there any solutions besides refactoring?
The :not rule is more specific, so it takes higher precedence.
If you can't refactor, you could put a bogus :not condition on the other rule as well, so they'll have the same precedence and thus revert to document order:
.grid:not(.ui) {
padding:25px;
background-color: red;
}
.grid:not(.nonexistentclassname) {
padding:50px;
background-color: green;
}
<li>
<div class="grid">
Test
</div>
</li>
You just need to make the selector you want to take precedence be more specific than the other one. If you add a "dummy" class to the element, you can add that class to your second selector to make it more specific (or at least make a tie where then, the last selector wins).
CSS Specificity is calculated as follows:
1000 points for an inline style
100 points for an id in the selector
10 points for a class or pseudo-class in the selector
1 point for an element or pseudo-element in the selector
In your case:
.grid:not(.ui)
Is worth 20 points because the selector has 1 class and one pseudo-classes in it.
But:
.grid
is only worth 10 points because of the one class.
/* This selector is worth 20 points */
.grid:not(.ui) {
padding:25px;
background-color: red;
}
/* This selector is also worth 20 points, but becomes it comes
after the other one, the location breaks the tie. */
.grid.special {
padding:50px;
background-color: green;
}
<li>
<!-- Adding another "dummy" class to the element allows you
to correctly find it with your CSS, and do it with a more
specific selector, if needed. -->
<div class="grid special">
Test
</div>
</li>
And, what if you need (for some reason) have the order of the selectors reversed? Just make the one that is suppose to "win" a little more specific:
/* This selector is worth 21 points */
div.grid.special {
padding:50px;
background-color: green;
}
/* This selector is worth 20 points */
.grid:not(.ui) {
padding:25px;
background-color: red;
}
<li>
<!-- Adding another "dummy" class to the element allows you
to correctly find it with your CSS, and do it with a more
specific selector, if needed. -->
<div class="grid special">
Test
</div>
</li>
Here's a great site for understanding how specificity is calculated that let's you "play" with selectors.
In your first example the .grid selectors each have a specificity value of 10 (classes = 10). Therefore, since both rules have the same specificity, their source order decides.
In your second rule, .grid:not(.ui) has a specificity value of 20 (2 classses; the :not() pseudo-class has no specificity value). The source order is subordinate because the rules have different specificity values.
So, to achieve your goal (the same behavior as before but with :not() applied to the first rule), you need to boost the specificity of the second rule by at least 10.
One method would be to add a useless :not() to the second rule. This method is described in another answer and is allowed by the spec:
6.6.7. The negation
pseudo-class
Note: the :not() pseudo allows useless selectors to be written. For
instance :not(*|*), which represents no element at all, or
foo:not(bar), which is equivalent to foo but with a higher
specificity.
.grid:not(.ui) {
padding:25px;
background-color: red;
}
.grid:not(.bar) {
padding:50px;
background-color: green;
}
<div class="grid">Test</div>
specificity calculator

Force to use style for a selector, no matter where it is in the dom

Say I would like to define a numbered circle, that looks like this:
http://jsfiddle.net/edi9999/6QJyX/
.number
{
border-radius: 50%;
width: 32px;
height: 24px;
text-align: center;
padding-top:8px;
font-size: 14px;
display:inline-block;
line-height: 16px;
margin-left:8px;
color:white;
background-color:black;
border-color:white;
}
I would like to add importance to the selector, so that no matter in what context the element is, an element with class number looks the same.
Here's an example of the code breaking: http://jsfiddle.net/edi9999/6QJyX/2/
A way to do this would be to add !important to all properties of the CSS, but I wonder if they could be other solutions, because it is a bit crappy.
I have added the private tag as that seems a bit like code-encapsulation.
Your best option is to increase the specificity of the selector. Other than that there is not much you can do.
#id .number
The ID selector will increase specificity so that only another ID in a selector will be able to override it.
http://jsfiddle.net/6QJyX/3/
Increasing the specificity of selectors will only lead to specificity wars (which leads to anger, which leads to hate, which leads to suffering). I would suggest decreasing the specificity of the selector that's causing the problem.
Pseudo code below:
.number {...}
.card span {...} // this selector is questionable
<div.number> this is styled correctly </div>
<div.card>
<span.number> this is styled incorrectly </span>
</div>
Why do all .card spans need to be styled a particular way? It seems as if the second selector is more like a grenade and less like a sniper—that is, it targets a blanket set of elements rather than just the ones you need.

Repurposing CSS Class Selectors

I don't know what this technique is called, I've only seen it used. It's a way to repurpose the same selectors with CSS.
For example if I create
h1 {
font-size:18px;
color:#FFFFFF;
font-family:Arial, Helvetica;margin:0;
padding:0;
}
h2 {
font-size:18px; color:#000000;
font-family:Arial, Helvetica;
font-weight:normal;margin:0;
padding:0;
}
I can repurpose the h selectors with something like
.whatever h1 {
color: #000;
font: 2.0em arial, sans-serif;
background-color: #fff3ea;
margin: 50px 0px 0px 50px;
}
.whatever h2 {
color: #000;
font: 1.7em bold arial, sans-serif;
background-color: #fff3ea;
margin: 25px 0px 25px 75px;
}
If h1 and h2 appear inside of a div called whatever, then they will assume those properties. You can do this with ID tags and class tags but I can't for the life of me remember how this is done.
Any thoughts?
This is called specificity.
It's a key feature of CSS which means properties in the more specific selector (.whatever h1) will override properties in less specific ones (h1). It allows you to set general styles for most of the elements on the page (e.g. all h1 elements), and then change the properties of a small subset of those elements using a more specific selector that identifies, for example, only the h1 elements inside another element whose class is whatever:
HTML
<h1>I'm green with envy</h1>
<h1>And so am I</h1>
<div class="whatever">
<h1>Because I'm rather special</h1>
</div>
CSS
h1{
color: green;
}
.whatever h1{
color: blue;
}
RESULT
The CSS selector .whatever h1 means "any h1 element inside another element with a class of whatever". You could also give the h1 element its own class to achieve the same effect; you just write the CSS slightly differently to reflect the fact that the h1 element you're targeting now has its own class:
HTML
<h1 class="whatever">I'm special</h1>
CSS
h1.whatever{
color: blue;
}
Always try to give your classes and IDs meaningful names that refer to the element's role within the page, rather than its colour or other attributes. i.e. It is much better to use ".introduction" instead of ".bigredtext" or ".whatever". That way, if you change the colour of your intro text to bright blue, you don't have to rename the class in your CSS and HTML, and everything in your HTML will read better too. (This is what people are talking about when they mention "semantics" and "semantic naming conventions".)
How specificity is determined (simple rules to remember)
User agents (web browsers) use a formula to calculate how specific each selector is and which should take precedence over the other. In very simple terms, from less specific to more specific:
Selectors with only the name of the element (e.g. h1) are the least specific of all
Selectors with a .class are more specific than selectors with no class
Selectors with an #id are more specific than selectors with a .class
Selectors lower down in a stylesheet take precedence over earlier identical selectors
Those are the four main rules worth learning about specificity, and they will cover most simple use cases. These two additional rules aren't related to specificity, but they're worth knowing too:
Inline styles such as <h1 style="color: blue"> will take precedence over external rules declared separately in external stylesheets or inside <style> tags. You probably shouldn't use inline styles, but it's worth knowing this just in case you come across them.
Properties within a selector that use the !important flag "trump" everything and can't be overruled. Likewise, you probably shouldn't choose to use the !important flag, but there are times when you may be forced to.
How specificity is really determined (how to calculate it precisely)
Of course, it gets a little more complicated than the above (but not by much) when you start chaining classes, IDs, and elements together, which is why it can be helpful to learn how to calculate specificity precisely rather than working on intuition alone, as it will save you a lot of time when your stylesheets get bigger and more complicated.
If you'd like to learn more, Smashing Magazine has a piece titled "CSS Specificity and Inheritance" that's worth a look. They reference Andy Clarke's famous Star Wars Chart, which might be an easier way to visualise specificity if you're familiar with Star Wars, but it will probably just make things even more confusing if you're not! (Click the image below to read more on Andy's site.)
You faced overriding the selectors.
example:
<div class="one">
<div id="two">
<h1> This is H1 text </h1>
</div>
</div>
so you have set H1 to FFF - white color by:
h1 {
color:#fff;
}
now we do first override ( using ID ):
div#two h1 {
color:#888;
}
and the third, notice you don't have to put current element, you can set it for each element with given class:
.one div#two h1 {
color:#000;
}
so in the end we have black text color.
The raw ones are to set "global" styling. The nested ones are to give exac styles to given elements.
Also you can use chaining class/id selectors for <div id="one" class="two three four"> you can select it using div#one.two.three.four - without spaces

Why are my CSS properties being overridden/ignored?

I'm having some issues with the CSS "hierarchy" (not sure if it's proper to call it a hierarchy). I'm trying to style the below bit of HTML.
<body>
<section id="content">
<article>
<ul class="posts-list">
<li class="post-item">
<h2>[post title]</h2>
<p class="item-description">...</p>
<p class="item-meta">...</p>
</li>
...
</ul>
</article>
</section>
</body>
Since section#content changes on every page I have, I wanted to maintain consistent styles across all of them, so I wrote some "global" CSS rules.
#content {
color: #000;
margin-left: 300px;
max-width: 620px;
padding: 0px 10px;
position: relative;
}
#content p,
#content li {
color: #111;
font: 16px / 24px serif;
}
I wanted to style HTML within a ul.posts-list differently, so I wrote these rules.
li.post-item > * {
margin: 0px;
}
.item-description {
color: #FFF;
}
.item-meta {
color: #666;
}
However, I ran into some issues. Here is how Chrome is rendering the CSS:
For some reason, the rules #content p, #content li are overriding my rules for .item-description and .item-meta. My impression was that class/id names are considered specific and thus higher priority. However, it seems that I have a misunderstanding of how CSS works. What am I doing wrong here?
Edit: Also, where can I read up more about how this hierarchy works?
Elements id have the priority in CSS since they are the most specific.
You just have to use the id:
#content li.post-item > * {
margin: 0px;
}
#content .item-description {
color: #FFF;
}
#content .item-meta {
color: #666;
}
Basically id have the priority on class which the priority on tags(p,li,ul, h1...). To override the rule, just make sure you have the priority ;)
The "hierarchy" in which CSS rules are measured is called specificity. Each part of a CSS rule has an actual numerical base-10 value. IDs are worth 100 while classes are only 10.
For more information see http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/
Targeting ID's is more specific than targeting classes. More specific styling will overwrite less specific styling. It should be noted that in-line styling in HTML is more specific and will therefore overwrite ID-targeted styling. In other words:
<p style="color:white" id="itemDescId" class="item-description">...</p>
With the CSS:
p{color:blue;}
#itemDescId{color:red;}
.item-description{color:green}
The text will appear white - not because it's closest to the html code, but because it's higher in the specificity hierarchy. If you remove the inline styling (and you normally should for cleaner more manageable code), then the text would become red. Remove the ID and it will be green. And finally it will be blue once the class is removed.
This is one of the more complex topics to understand in CSS, and I'm only scratching the surface, but the easiest description I've found on how CSS specificity works is over at CSS tricks:
http://css-tricks.com/specifics-on-css-specificity/
My response should have been a "comment" on the answer, but I have the correct fix although #tibo answered correctly:
li.post-item > * {
margin: 0px !important;
}
.item-description {
color: #FFF !important;
}
.item-meta {
color: #666 !important;
}
The !important rule will override the order of evaluation between id and class.
Here is a link to an article, When Using !important is The Right Choice, that will help you to understand... it made my life easier :)
Better to follow the CSS standards.
choose css selector and makeit under its parent then u may not to get conflicts when loading css fles (like .css files)

Resources