CSS Specificity

An example showing specificity calculation. Source: Bostian 2019.
An example showing specificity calculation. Source: Bostian 2019.

Assume an element on a web document is targeted by two different CSS selectors. Each selector applies different styling to that element. The selector with the higher specificity will take effect. CSS defines clear rules to determine the specificity of CSS selectors.

A good understanding of the rules of CSS specificity can enable developers write better selectors and troubleshoot problems in their stylesheets. Otherwise, developers may end up misusing !important in their CSS declarations, thus making code more difficult to maintain in the long run.

Discussion

  • What are the rules to determine CSS specificity?
    Template for calculating specificity of a CSS selector. Source: Chijioke 2019.
    Template for calculating specificity of a CSS selector. Source: Chijioke 2019.

    A CSS selector will typically use ID, class, element/tag name or a combination of these. In addition, some selectors will use element attributes, pseudo-classes and pseudo-elements. Specificity is computed by counting each of these and ranking them. IDs have more importance than classes, pseudo-classes and attributes; the latter have more importance than elements and pseudo-elements. Inline style, specified as attribute style="…", has highest importance. The counts are concatenated to arrive at the final specificity. A selector with a higher number to the left implies higher specificity.

    If two selectors have the same specificity, one that appears later in the stylesheet is applied. Universal selector * and combinators (~, >, +) are ignored. Pseudo-class :not() is not counted but selectors inside it are counted.

    Although specificity is calculated for selectors, styles are applied based on individual property-value declarations. Regardless of specificity, declarations with !important have highest importance. If conflicting declarations contain !important, higher specificity wins.

    If a selector has no declaration for a specific property, inherited value (if available) or initial value is applied.

  • Could you explain CSS specificity with an example?

    Given an ID, three classes and two elements, specificity is 0-1-3-0. This has higher specificity than a selector with just five classes, where specificity is 0-0-5-0.

    Consider HTML content <p class="foo" id="bar">Lorem ipsum.</p>. Consider CSS rules p { color: red; }, .foo { color: green; } and #bar { color: blue; }. All three selectors target the paragraph but the last selector has highest specificity. Hence, we'll see blue-coloured text. This can be understood by calculating the specificity:

    • p: one element: 0-0-0-1
    • .foo: one class: 0-0-1-0
    • #bar: one ID: 0-1-0-0

    Since 0-1-0-0 > 0-0-1-0 > 0-0-0-0, #bar selector has the highest specificity.

    If we have p { color: red !important; }, we'll have red-coloured text. Specificity is ignored.

    Suppose we introduce inline styling, <p class="foo" id="bar" style="color: purple">…</p>. This will take precedence, unless there's an earlier declaration with !important.

    Suppose we have two classes <p class="foo hoo">…</p> styled with .hoo { color: yellow; }. Specificity is the same for both .foo and .hoo. If .hoo appears later in the stylesheet, we'll have yellow-coloured text. When specificity is same, order matters.

  • How is specificity affected by cascading order?

    Consider HTML content <p class="foo" id="bar">Lorem ipsum.</p>. Suppose the author defines .foo { color: green; } and the user defines #bar { color: blue; }. User-defined styles are typical for accessibility reasons. The latter has higher specificity but the former declaration is used; that is, text is rendered in green. To understand this, we need to understand the concept of origin.

    CSS styles can come from different origins: user (reader of the document), user agent (browser), or author (web developer). The standard defines precedence of the origin. This is applied first before specificity is considered. The order also considers declarations that include !important.

    Precedence in descending order is Transition declarations, Important user agent declarations, Important user declarations, Important author declarations, Animation declarations, Normal author declarations, Normal user declarations, and Normal user agent declarations.

  • What are some examples of CSS specificity calculation?
    Examples showing CSS specificity calculation. Source: Adapted from Coyier 2018.
    Examples showing CSS specificity calculation. Source: Adapted from Coyier 2018.

    Here we share a few examples:

    • ul#nav li.active a: #nav is the ID, .active is the class, and three elements ul, li and a are used. Specificity 0-1-1-3.
    • body.ie7 .col_3 h2 ~ h2: Two classes ie7 and .col_3, and three elements body, h2 and h2 are used. ~ is not counted. Specificity 0-0-2-3.
    • <li style="color: red;">: Has inline style attribute. Specificity 1-0-0-0.
    • ul > li ul li ol li:first-letter: Apart from six elements, :first-letter is a pseudo-element. > is not counted. Specificity 0-0-0-7.
    • li:nth-child(2):hover: Both :nth-child(2) and :hover are pseudo-classes. Specificity 0-0-2-1.
    • .bar1.bar2.bar3.bar4: This is a combined selector with four classes. Specificity 0-0-4-0.
  • What are some tips for managing CSS specificity?
    A handy CSS specificity cheatsheet. Source: Clarke 2005.
    A handy CSS specificity cheatsheet. Source: Clarke 2005.

    Use IDs to increase specificity. For example, a#foo has higher specificity compared to a[id="foo"]: 0-1-0-1 > 0-0-1-1.

    When two selectors have same specificity, the selector defined second takes precedence. The use of !important overrides specificity. If two declarations have !important, the second one wins. In any case, avoid the use of !important.

    For link styling, define CSS rules in the order of Link, Visited, Hover, Active (LVHA).

    In terms of online resources, developers can consult handy cheat sheets on CSS specificity at Stuff & Nonsense or at Standardista. There's also an online calculator.

  • I find CSS specificity confusing. Is there a simpler way?

    One approach is to adopt a naming convention such as Block-Element-Modifier (BEM). By defining CSS classes for design components (called blocks), scope of a class is "limited" to that block.

    In BEM, selectors use only classes. IDs and elements are avoided in selectors. Combined selectors (of the form .foo.bar) are avoided. Nested selectors (of the form .foo .bar) are allowed but discouraged in BEM. Since selectors are just classes, it's easier to determine specificity. Selectors can be reused more easily.

    CSS Modules offers a modern way to restrict the scope of CSS declarations. Via tooling, this automatically renames the selectors. This can be configured to adopt BEM naming approach. For example, a menu component is styled with .Menu_item--3FNtb. If it appears within a header, the style changes to .Header_item--1NKCj. Although both have same specificity, the latter occurs later in the stylesheet.

    One alternative to BEM is Enduring CSS (ECSS). Partly inspired by BEM, ECSS promotes the use of single class selectors. IDs and tag names are not used in selectors. Nested selectors are allowed.

    Other alternatives include Atomic CSS (ACSS), Object-Oriented CSS (OOCSS), Scalable and Modular Architecture for CSS (SMACSS).

  • Is CSS specificity still relevant in modern JavaScript frameworks?

    Among the well-known JavaScript frameworks are Angular, React and Vue. All of these offer ways to style documents in a modular fashion. This is in contrast to the default global scope of CSS selectors and declarations. In Angular and React, a styled component would have declarations that are applicable only to that component. In Vue, scoped CSS achieves the same effect.

    This idea of combining JS and CSS has been formalized under the term CSS-in-JS. However, one disadvantage is that we're combining HTML structure and styling into a component file. Although this isolates one component from another, it also makes styles harder to reuse across components.

    Although CSS declarations are restricted to their components, specificity can't be ignored. Specificity still applies within the component but a lot easier to manage.

Milestones

Dec
1996

W3C publishes CSS1 as a W3C Recommendation. This clarifies the precedence when conflicting rules target the same element. It also explains how to calculate the specificity of selectors.

2000

There's no exact date when developers recognize the importance of CSS specificity. Probably around 2000 (plus or minus a few years), as websites and stylesheets start to grow in complexity, developers have a hard time debugging and maintaining their code. It's at this point that they begin to learn and understand CSS specificity.

Aug
2002

W3C publishes the first draft of CSS2.1, which is a revision of CSS2 from 1997. This clarifies the cascading order. In descending order, it's user important, author important, author normal, user normal and user agent declarations. In CSS1, precedence in descending order was author, reader and user agent declarations.

Jan
2006

Developer Keegan Street open sources a JavaScript module that, given a selector, calculates and return its specificity. This is a command-line tool. For convenience, an online version of this calculator is available.

Jan
2013

In W3C Working Draft titled CSS Cascading and Inheritance Level 3, cascading order is updated. This document becomes a W3C Candidate Recommendation in April 2015.

References

  1. Aderinokun, Ire. 2016. "The Effect of Importance and Origin on CSS Specificity." bitsofcode, January 19. Accessed 2020-10-14.
  2. BEM. 2020. "CSS with BEM." BEM. Accessed 2020-10-15.
  3. Barral, David. 2018. "Using BEM conventions in CSS modules leveraging custom webpack loaders." Trabe, September 24. Accessed 2020-10-15.
  4. Bos, Bert. 2016. "20 Years of CSS." W3C, December 17. Accessed 2020-10-15.
  5. Bos, Bert, Tantek Çelik, Ian Hickson, and Håkon Wium Lie, (eds). 2011. "Chapter 6: Assigning property values, Cascading, and Inheritance." In: Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification, W3C Recommendation, June 7. Updated 2016-04-12. Accessed 2020-10-15.
  6. Bostian, Emma. 2019. "CSS Specificity." Dev.to, January 21. Accessed 2020-10-14.
  7. Carlson, Laura L. 2002. "Calculating Specificity." University of Minnesota. Accessed 2020-10-14.
  8. Chijioke, Kingsley Silas. 2019. "What is CSS Specificity and How Does it Work?" Tutorial, Envato Tuts+, October 31. Accessed 2020-10-14.
  9. Churcher, Ali. 2018. "Overriding styles with CSS Modules: Where's my specificity?" LieferFactory GmbH, June 27. Accessed 2020-10-14.
  10. Clarke, Andy. 2005. "CSS Specificity Wars." Stuff & Nonsense, October 7. Updated 2018. Accessed 2020-10-15.
  11. Coyier, Chris. 2018. "Specifics on CSS Specificity." CSS-Tricks, February 26. Accessed 2020-10-14.
  12. Etemad, Elika J., and Tab Atkins, (eds). 2018. "CSS Cascading and Inheritance Level 3." W3C Candidate Recommendation, August 28. Accessed 2020-10-15.
  13. Friedman, Vitaly. 2007. "CSS Specificity: Things You Should Know." Smashing Magazine, July 27. Accessed 2020-10-14.
  14. Hiljá. 2014. "OOCSS, ACSS, BEM, SMACSS: what are they? What should I use?" Clubmate, January 23. Accessed 2020-10-15.
  15. Lie, Håkon Wium, and Bert Bos. 1996. "Cascading Style Sheets, level 1." W3C Recommendation, December 17. Accessed 2020-10-14.
  16. Lie, Håkon Wium, Elika J. Etemad, and Tab Atkins, (eds). 2013. "CSS Cascading and Inheritance Level 3." W3C Working Draft, January 3. Accessed 2020-10-15.
  17. Manchanda, Harry. 2017a. "The State of CSS Specificity, Part 2." CodingGame. Accessed 2020-10-14.
  18. Manchanda, Harry. 2017b. "The State of CSS Specificity, Part 3." Tech.io. Accessed 2020-10-14.
  19. Sandro. 2019. "Is BEM still a thing in a component-based world?" Dev.to, July 26. Accessed 2020-10-15.
  20. Singh, Kalpesh. 2016. "5 Things You Should Know About CSS Specificity." Onextrapixel, April 7. Accessed 2020-10-15.
  21. Street, Keegan. 2018. "keeganstreet/specificity." GitHub, August 28. Accessed 2020-10-14.
  22. The Electric Toolbox. 2008. "Using !important with CSS." The Electric Toolbox Blog, April 7. Updated 2020-01-02. Accessed 2020-10-15.
  23. Weyl, Estelle. 2012. "CSS Specificity." Standardista, January 8. Updated 2017-06-02. Accessed 2020-10-14.
  24. Çelik, Tantek, Elika J. Etemad, Daniel Glazman, Ian Hickson, Peter Linss, and John Williams. 2018. "Selectors Level 3." W3C Recommendation, November 6. Accessed 2020-10-14.

Further Reading

  1. Friedman, Vitaly. 2007. "CSS Specificity: Things You Should Know." Smashing Magazine, July 27. Accessed 2020-10-14.
  2. Coyier, Chris. 2018. "Specifics on CSS Specificity." CSS-Tricks, February 26. Accessed 2020-10-14.
  3. Çelik, Tantek, Elika J. Etemad, Daniel Glazman, Ian Hickson, Peter Linss, and John Williams. 2018. "Selectors Level 3." W3C Recommendation, November 6. Accessed 2020-10-14.
  4. MDN Web Docs. 2020. "Specificity." MDN Web Docs, April 20. Accessed 2020-10-14.
  5. Carrer, Vladimir. 2009. "CSS Specificity - Cheat Sheet." Blog, September 29. Accessed 2020-10-14.

Article Stats

Author-wise Stats for Article Edits

Author
No. of Edits
No. of Chats
DevCoins
4
0
1237
1378
Words
0
Likes
6430
Hits

Cite As

Devopedia. 2020. "CSS Specificity." Version 4, December 11. Accessed 2024-06-26. https://devopedia.org/css-specificity
Contributed by
1 author


Last updated on
2020-12-11 13:20:14