Precedence in CSS Selector Specifity Conflicts (Type VS Class Selector)

Precedence in CSS selector specifity conflicts (type vs class selector)

TL;DR Answer

The first rule is more specific than the second one because it has both a type and attribute part for the selector, and thus has precedence:

input[type="text"] { }         /* type + attribute for specificity */
.top_bar_login_form_input { } /* only class for specificity, so *less* specificity */

Longer answer

You'd think that the type="text" bit, which is an attribute selector, is more specific than a class selector, in accordance with the MDN page on specificity:

The following list of selectors is by increasing specificity:

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

The above quote was in the MDN article at the time this answer was written.

Why that is misleading:

(Tanks to @BoltClock's insights.)

The above only seems correct, but that's because you typically include the element in the selector (e.g. input[type="text"]) when doing an attribute selector. However, what's sneaky: the input bit matters.

Suppose we have the following markup:

<input class="my-class" type="text" value="some value" />

In the following scenario the input renders red:

[type="text"] { color: green; }
.my-class { color: red; } /* last rule matched */

If we reverse the rules in a scenario, the input will render green:

.my-class { color: red; }
[type="text"] { color: green; } /* last rule matched */

This is because both selectors have equal specificity. Now introducing the input selector to the attribute rule will make one of them more specific, which can be seen in this scenario:

input[type="text"] { color: green; }  /* most _specific_ rule matched */
.my-class { color: red; }

The W3 spec makes my head hurt, but it does have the details on why the above works. See also the answer by @BoltClock and comments in those code examples for info on how the specificity is calculated.

What is the order of precedence for CSS?

There are several rules ( applied in this order ) :

  1. inline css ( html style attribute ) overrides css rules in style tag and css file
  2. a more specific selector takes precedence over a less specific one
  3. rules that appear later in the code override earlier rules if both have the same specificity.
  4. A css rule with !important always takes precedence.

In your case its rule 3 that applies.

Specificity for single selectors from highest to lowest:

  • ids (example: #main selects <div id="main">)
  • classes (ex.: .myclass), attribute selectors (ex.: [href=^https:]) and pseudo-classes (ex.: :hover)
  • elements (ex.: div) and pseudo-elements (ex.: ::before)

To compare the specificity of two combined selectors, compare the number of occurences of single selectors of each of the specificity groups above.

Example: compare #nav ul li a:hover to #nav ul li.active a::after

  • count the number of id selectors: there is one for each (#nav)
  • count the number of class selectors: there is one for each (:hover and .active)
  • count the number of element selectors: there are 3 (ul li a) for the first and 4 for the second (ul li a ::after), thus the second combined selector is more specific.

A good article about css selector specificity.

Multiple !important class declarations and precedence

According to this source: http://www.boogiejack.com/CSS_4.html

class2 should override the class1 styling.

Order of Specification: As a last
resort, when all other conflict
resolution specifications cannot
determine which style should take
precedence, the last style specified
will be the style used.

CSS precedence

As others have mentioned, you have a specificity problem. When determining which of two rules should take precedence, the CSS engine counts the number of #ids in each selector. If one has more than the other, it's used. Otherwise, it continues comparing .classes and tags in the same way. Here, you have a class on the stylesheet rule, but not on the inline rule, so the stylesheet takes precedence.

You can override this with !important, but that's an awfully big hammer to be using here. You're better off improving the specificity of your inline rule. Based on your description, it sounds like your .rightColumn element either is or contains a table and you'd like the cells in that table to have extra spacing? If so, the selector you're looking for is ".rightColumn td", which is more specific than the stylesheet rule and will take precedence.

CSS Selectors conflicting

Rules that appear later in the code override earlier rules if both have the same specificity.

I presume you got td.lblcontainer input[type="radio"] defined later in your CSS file. Either put it above, or instead do

td.lblcontainer > input[type="radio"]{
*css values*
}

div.calChooser input[type="radio"]{
*css values*
}

Note the > selector only targets first-level children, therefore won't affect the input inside your div.

CSS Specificity - Defining Classes & IDs


  1. Firstly, when relating to CSS specificity, I've noticed that one source includes pseudo elements in the calculation, while another tells you to leave them out of the calculation. Is this purely an optional thing, or should I include them?

    This is news to me; it looks like pre-CSS2.1 pseudo-elements were originally supposed to be ignored when calculating selector specificity. The article that says to leave them out of the calculation was published almost a decade ago, right in the middle of CSS level 2's refactoring. Here's what the 1998 CSS2 recommendation says (which, for reference, is also quoted in that article, but the URL that it links to redirects to the latest revision of the spec where it's changed):

    A selector's specificity is calculated as follows:

    • count the number of ID attributes in the selector (= a)
    • count the number of other attributes and pseudo-classes in the selector (= b)
    • count the number of element names in the selector (= c)
    • ignore pseudo-elements.

    In CSS2.1, as well as the latest Selectors standard, pseudo-elements must be counted like normal type selectors when calculating specificity.

    Perhaps what's even more curious is that CSS1 had the same rule for pseudo-elements in terms of specificity as the current standard:

    Pseudo-elements and pseudo-classes are counted as normal elements and classes, respectively.

    This leads me to believe that the change in CSS2.0 was ultimately reversed in CSS2.1 so it wouldn't break existing (legacy) stylesheets that happened to rely on the behavior, and/or because it simply didn't make sense not to include pseudo-elements since you apply styles to them like you do with actual elements.


  2. Secondly, is there any specific reason why I should declare classes above identifiers? For instance, I've already sectioned my development CSS file, and in the 'footer' section, I have #footer, #footer-container, .grid and .one-third, declared in this order. Is this perfectly fine, or should I switch them around?

    There should be no difference whether you place your classes before your IDs, as long as your two classes follow the order they are in and your two IDs, likewise. Even assuming that all of these rules happen to match the same element, the IDs should take precedence over the classes for any properties that need to be overridden.


  3. Lastly, just a quick question about listing CSS properties in alphabetical order. I fully understand that this is optional, but using my declaration for #footer above as an example, is there any preference for border, margin or padding, as in alphabetical (bottom; left; right; top), or declared as written in shorthand (top; right; bottom; left)?

    If you are declaring the longhand properties separately, then it's entirely up to you how you want to order them. I would certainly follow the order already laid out by the shorthands for the sake of simplicity.

    FYI, the order in the shorthands is laid out the way it is because if you literally connect the dots, the order is actually clockwise starting from the top.

What are the priorities among CSS selectors

The gory details in the spec are actually reasonably readable. In summary:

  1. !important rules and inline style rules win most.

  2. Otherwise, normally the more specific wins. #id is a more specific selector than .classname is a more specific selector than tagname.

  3. Where rules are equally specific, the one declared last wins.

There is no particular reason why this ‘shouldn't happen’. It's normal to specify a broad-brush rule and then add a more specific rule to target one case; multiple same-property rules on a single element are not unusual or undesirable.

Confusing CSS rules precedence

The cascade works like this:

  1. The more important rule applies.
  2. If equally important, the more specific rule applies.
  3. If equally specific, the latter rule applies.

Here, #topnav li has a specificity of 101, and #last-nav has a specificity of 100, so the first one wins. A selector of li#last-nav or #topnav #last-nav would be more specific.

Calculating CSS selector specificity for :not() pseudo-class

Assuming both of them apply to one element, should these two be calculated as (0011) and therefore they should be ordered according to order of appearance? Or should the selectors inside the :not() pseudo-class be further calculated separately depending on which one match as a second step to determine the one that have precedence over the other?

If you're implementing Selectors 3, they should not be counted at all. As already mentioned, both of your selectors are invalid according to that spec because it only defines :not() to accept a single simple selector at a time.

If you expand them out so that they validate (following the instructions/examples given here), then their specificities will be calculated as follows:

/* 2 attributes, 1 class, 1 type -> specificity = 0-3-1 */
input:not([type="text"]):not([type="password"]):not(.someClass)

/*
* 1 ID, 1 type -> specificity = 1-0-1
* 1 attribute, 1 type -> specificity = 0-1-1
*/
input:not(#someId), input:not([type="text"])

Because Selectors 3 says:

Selectors inside the negation pseudo-class are counted like any other, but the negation itself does not count as a pseudo-class.

Also, in response to your comment:

True, according to specs, simple selectors only. But some browsers support multiple ones. Some of them don't, and some dropped them later. Also, you can write the same rule even with simple selectors like this instead: input:not([type="text"]):not([type="password"]):not(.someClass) which is better and work as well. Does this mean it should be calculated as 0031, then? How about those that support multiple ones, how do they calculate?

The only browser I know of that has ever supported multiple selectors within :not() is Firefox 3.0, and it does so because of a bug. Selectors 3 never allowed :not() to contain multiple selectors — that is only introduced in Selectors 4, for which specificity calculation hasn't even been clearly defined yet1, so even if you were trying to implement Selectors 4 (which I seriously doubt you are), you'll be stuck.

It's not clear to me how Firefox 3.0 implemented specificity with its version of the :not() selector and I don't have a copy of it to test with, but I think it's safe to assume that it doesn't matter anymore as it was never the intended behavior anyway. OK so I picked up Firefox 3.0 beta 1, 3.0.0, 3.0.18 and 3.1 beta 1, and none of them reproduce this behavior at all. So there you have it.


1 Note that both the current 2013 ED and the 2011 FPWD are consistent in saying that the specificity of :not() is equal to that of its most specific argument, but this may change in the future.



Related Topics



Leave a reply



Submit