This site is designed for accessibility. Content is obtainable and functional to any browser or Internet device. This site's full visual experience is available in a graphical browser that supports web standards. Please consider upgrading your web browser.

Calculating Specificity

At its core, specificity is the mechanism by which the rest of CSS works. It is used to decide which selectors are more specific than others, and therefore which rules will apply to a given element. For example, consider the following:

p.warning {color: red;} */ specificity = 0-1-1 */
div table p {color: magenta;} */ specificity = 0-0-3 */

Okay, now assume that you have a paragraph with a class of warning which is found inside a table which is contained within a div. Both rules apply to the paragraph in question-- so which one is used? A first reaction might be to say that the second wins, because it comes later in the stylesheet. That is, after all, one of the rules of CSS. However, the rules state that if two selectors have the same specificity, origin, and so on, then the later one wins.

Our example rules don't have the same specificity. Therefore, the rule whose selector has a higher specificity will win, and warning paragraphs will be the appropriate color. In this case, it's the first rule, so they'll be red. However, if we change the rules like this:

p.warning {color: red;} */ specificity = 0-1-1 */
div table p.warning {color: magenta;} */ specificity = 0-1-3 */

Now the second rule has a higher specificity, so it wins out, regardless of whether it comes before or after the first rule. In other words, I could also have reversed the order of the rules, and the 'magenta' rule would still be more specific than the 'red' one. Thus warning paragraphs inside tables which are inside divs will be magenta. Of course, warning paragraphs in any other context will still be red, since the 'red' rule matches all warning paragraphs, regardless of their location.

A selector's specificity is calculated as follows:

  1. Count
    1. #IDs in the selector (= a).
    2. Oher attributes and pseudo-classes in the selector (= b)
      • [attributes]
      • .classes
      • pseudo classes =
        • :first-child
        • :link
        • :visited
        • :hover
        • :actice
        • :focus
        • :lang
    3. Element names in the selector (= c)
      • Ignore the univeral selector *
      • Ignore pseudo-elements:
        • :first-letter
        • :first-line
        • :before
        • :after
  2. Concatenate the three numbers. Specificity = a-b-c

Example 1.
ul li em

Specificity=
0-0-3

Selects any em element that is a descendant of a li element that is a descendant of an ul element.

  1. Number of #IDs = 0
  2. Number of other attributes and pseudo-classes = 0
  3. Number of element names = 3
    em element
    li element
    ul element

Example 2.
body#home *.example

Specificity=
1-1-1

Selects any element with a class attribute that contains the word example that is a descendant of a body element with an id attribute that equals home.

  1. Number of #IDs = 1
    #home
  2. Number of other attributes and pseudo-classes = 1
    .example
  3. Number of element names = 1
    body element
    (universal selector * ignored)

Example 3.
p.footer a:hover

Specificity=
0-2-2

Selects any a element which is in a hover state that is a descendant of a p element with a class attribute that contains the word footer.

  1. Number of #IDs = 0
  2. Number of other attributes and pseudo-classes = 2
    :hover
    .footer
  3. Number of element names = 2
    a element
    p element

Example 4.
h1 + * p

Specificity=
0-0-2

Selects any p element that is a descendant of any element that immediately follows (is sibling to) a h1 element.

  1. Number of #IDs = 0
  2. Number of other attributes and pseudo-classes = 0
  3. Number of element names = 2
    p element
    h1 element
    (universal selector * ignored)

Example 5.
body > .aside > ul a:visited

Specificity=
0-2-3

Selects any a element whose target has been visited that is a descendant of an ul element that is a child of any element with a class attribute that contains the word aside that is a child of a body element.

  1. Number of #IDs = 0
  2. Number of other attributes and pseudo-classes = 2
    :visited
    .aside
  3. Number of element names = 3
    a element
    ul element
    body element

Example 6.
a:link:hover img[alt]

Specificity=
0-3-2

Selects any img element with an alt attribute that is a descendant of an a element whose target has not been visited and which is in a hover state.

  1. Number of #IDs = 0
  2. Number of other attributes and pseudo-classes = 3
    [alt]
    :hover
    :link
  3. Number of element names = 2
    img element
    a element

Example 7.
div[title] + * #que > li

Specificity=
1-1-2

Selects any li element that is a child of any element with an #ID that equals que that immediately follows (is sibling to) a div element with a title attribute.

  1. Number of #IDs = 1
    #que
  2. Number of other attributes and pseudo-classes = 1
    [title]
  3. Number of element names = 2
    li element
    div element
    (universal selector * ignored)

Example 8.
p[class~="help"]:first-child:first-line

Specificity=
0-2-1

Selects the first displayed line in a p element with a class attribute that contains the word help and that is a first child.

  1. Number of #IDs = 0
  2. Number of other attributes and pseudo-classes = 2
    [class~="help"]
    :first-child
  3. Number of element names = 1
    p element
    (psuedo-element :first-line ignored)

Example 9.
* + * > * * > * + * *

Specificity=
0-0-0

Selects any element that is a descendant of any element that immediately follows (is sibling to) any element that is a child of any element that is a descendant of any element that is a child of any element that immediately follows (is sibling to) any element.

  1. Number of #IDs = 0
  2. Number of other attributes and pseudo-classes = 0
  3. Number of element names = 0
    (universal selector * ignored)

Example 10.
html:lang(en) body div.ii table tr td p:first-letter

Specificity=
0-2-7

Selects the first letter of a p element that is a descendant of a td element that is a descendant of a tr element that is a descendant of a table element that is a descendant of a div element with a class attribute that contains the word ii that is a descendant of a body element that is a descendant of a html element which is in a language or locale whose identifier equals en or begins with en-.

  1. Number of #IDs = 0
  2. Number of other attributes and pseudo-classes = 2
    .ii
    :lang(en)
    (psuedo-element :first-letter ignored)
  3. Number of element names = 7
    p element
    td element
    tr element
    table element
    div element
    body element
    html element

Summary

Simple or not, specificity is a cornerstone of the CSS specification, and it's all too often misunderstood. By thoroughly understanding its behavior, authors can avoid a number of common mistakes in selector construction and the order in which selectors are written. The payoffs range from diagnosing places where one selector vastly outweighs another to figuring out which pseudo-classes need to come last. Although the clash over inline style specificity has yet to play out to its conclusion, for the moment authors can generally rely on inline styles winning out over embedded or external styles. All in all, it behooves every CSS author to study specificity closely and understand it completely.