Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't the CSS ID the highest priority CSS rule in this case?

I have built a CSS navigation header, and it's working exactly the way I want in regards to positioning, stylization, all that. This is the CSS that stylizes it:

#header ul {
padding:72px 0 0 0;
text-align:center;
}

#header ul, #header ul li {
margin:0;
list-style:none;
}

#header ul li {
display:inline;
}

#header ul li a {
font-size:17px; color:#69C; text-decoration:none;
display:inline-block;
height:44px;
line-height:44px;
margin:3px 6px;
padding:0 26px;
}

#header ul li a:hover {
background:#69C;
color:#FFF;
}

And this is the list:

<div id="#header">
   <ul>
      <li><a href="#">HOME</a></li>
      <li><a href="#">WHAT WE DO</a></li>
      <li><a href="#">ABOUT US</a></li>
      <li><a href="#" id="get_started">GET STARTED TODAY!</a></li>
   </ul>
</div>

Pretty simple stuff (and currently viewable at http://www.pmind.com/staging, but I included the code here for potential future readers).

You may notice in the list, the final li has an ID assigned to it. When I add this rule to the CSS:

#get_started {
color:#3C0;
}

Nothing happens. It was my understanding that A. CSS rules that come later in the CSS document have priority over rules that come earlier, and B. CSS rules used with the ID selector had the highest priority no matter what. But clearly the blue colourization that comes from the earlier CSS rules is still taking priority over colouring the final li green. I tried to make sure I did my due diligence Googling for the solution, but everything I find says that IDs get the highest priority (and this has also been my understanding in practice for everything I've coded before this one issue).

like image 332
Michael Davis Avatar asked Nov 11 '10 17:11

Michael Davis


2 Answers

If you were trying to override a selector that didn't have an ID with one that did, your confusion would be spot on.

In this case, though, you're using #get_started (which has an ID) to override #header ul li a which also has an ID in it.

Surely you're thinking that your ID is more specific than the #header ID — and you're not entirely wrong — but that's not how CSS works. It only cares about the number of IDs used in the selector, not which elements those IDs happen to target.

To figure out which of two selectors takes precedence, first count the IDs in each. If one has more IDs than the other, it wins and you're done.

If it's the same number (in this case both have one) move on to the number of classes. Again, if one has more classes than the other, it wins and you're done. In this case, both have zero classes.

So we move on to the number of tag names. Once again, if one has more tag names it wins. And here #header ul li a has three tags in it (ul, li, and a) whereas #get_started has none. You lose. The existing selector wins.

You could work around this with just #header #get_started which now has two IDs, but my preference would be to more clearly describe it as:

#header ul li a#get_started
like image 112
VoteyDisciple Avatar answered Sep 28 '22 05:09

VoteyDisciple


#header ul li a has a higher specificity than #get_started

You should read the w3c specs on specificity.

EDIT to add:

Just remember that although specificity is commonly written in short-hand as powers of 10, 10 elements will never be more specific than one class, and 10 classes will never be more specific than one id.

E.X.

html body div table tbody tr td ul li a is less specific than .some-link-class

like image 40
zzzzBov Avatar answered Sep 28 '22 03:09

zzzzBov