阿里云主机折上折
  • 微信号
Current Site:Index > The priority calculation rules of CSS

The priority calculation rules of CSS

Author:Chuan Chen 阅读数:59291人阅读 分类: CSS

The specificity of CSS determines which styles will be applied when multiple rules target the same element. Understanding these rules is crucial for writing maintainable stylesheets.

Basic Concepts of Specificity

CSS specificity is calculated using a weighting system, where rules with higher weights override those with lower weights. Specificity is determined by the type and quantity of selectors, not the order of the code (unless the weights are equal, in which case the latter-defined rule takes effect).

Selector Weight Calculation Rules

CSS specificity weight consists of four parts, listed in order of importance from highest to lowest:

  1. !important declarations
  2. Inline styles (style attribute)
  3. ID selectors
  4. Class selectors, attribute selectors, and pseudo-classes
  5. Element selectors and pseudo-elements

The weight is not calculated by simple addition but rather in a digit-like manner: (a, b, c, d)

  • a: Whether !important is used
  • b: Number of ID selectors
  • c: Number of class, attribute, and pseudo-class selectors
  • d: Number of element and pseudo-element selectors

Weight Calculation Examples

/* Weight: 0,0,0,1 */
p {
  color: blue;
}

/* Weight: 0,0,1,0 */
.text {
  color: red;
}

/* Weight: 0,0,1,1 */
p.text {
  color: green;
}

/* Weight: 0,1,0,0 */
#main {
  color: purple;
}

/* Weight: 0,1,1,1 */
#main p.highlight {
  color: orange;
}

/* Weight: 1,0,0,0 */
.special {
  color: black !important;
}

Handling Special Cases

The !important Rule

!important overrides all other rules (except higher-priority !important declarations), but it should be used sparingly:

.button {
  background: blue !important;
}

/* This will not override the rule above */
#special-button {
  background: red;
}

Inline Styles

Using the style attribute directly on an HTML element has very high specificity:

<p style="color: pink;">This text is pink</p>

Universal Selector and Inheritance

The universal selector (*) and inherited styles have the lowest specificity:

/* Weight: 0,0,0,0 */
* {
  margin: 0;
}

/* Inherited styles can be overridden by any explicit rule */
body {
  font-family: Arial;
}

Weight Calculation for Complex Selectors

When selectors are combined, their weights are calculated separately and then summed:

/* Weight: 0,0,2,1 (0,0,2,1) */
ul.menu li.active {
  background: yellow;
}

/* Weight: 0,1,1,1 (0,1,1,1) */
#sidebar ul.menu li {
  background: gray;
}

Specificity of Pseudo-Classes and Pseudo-Elements

Pseudo-classes and pseudo-elements belong to different categories in specificity calculation:

/* Weight: 0,0,1,1 */
a:hover {
  color: red;
}

/* Weight: 0,0,0,2 */
p::first-line {
  font-weight: bold;
}

Specificity of Attribute Selectors

Attribute selectors have the same weight as class selectors:

/* Weight: 0,0,1,0 */
[type="text"] {
  border: 1px solid #ccc;
}

/* Weight: 0,0,1,1 */
input[type="text"] {
  padding: 5px;
}

Impact of Selector Combinations

Different ways of combining selectors affect the final weight:

/* Weight: 0,0,0,2 */
div p {
  margin: 10px;
}

/* Weight: 0,0,0,1 + 0,0,0,1 = calculated separately */
div, p {
  padding: 5px;
}

Specificity Issues in Practical Applications

In real-world projects, specificity conflicts are common:

<style>
  .card { background: white; }  /* Weight: 0,0,1,0 */
  #featured .card { background: yellow; }  /* Weight: 0,1,1,0 */
  body.home #featured .card { background: orange; }  /* Weight: 0,1,2,0 */
</style>

<div id="featured">
  <div class="card">Card content</div>
</div>

Avoiding Overly High Specificity

Over-reliance on high-specificity selectors makes styles hard to maintain:

/* Bad practice - overly high specificity */
body.home #main #content .article ul li a {
  color: blue;
}

/* Better approach - keep specificity low */
.article-link {
  color: blue;
}

Debugging Specificity Issues

When styles don't apply as expected:

  1. Use browser developer tools to inspect applied styles
  2. Check which rules are overridden (usually shown with strikethrough)
  3. Pay attention to the calculated specificity weights
<style>
  .title { color: red; }
  h1 { color: blue; }
</style>

<h1 class="title">Heading color</h1>

Impact of CSS Preprocessors

Nested selectors generated by Sass/Less can produce high specificity:

// Compiled output may have high-specificity selectors
.menu {
  ul {
    li {
      a {
        color: red;
      }
    }
  }
}

Performance Considerations

While modern browsers are well-optimized, overly complex selectors can still impact performance:

/* Poor performance */
div:nth-child(2n+1) > span[data-value^="prefix"] ~ a:hover::before

/* Better performance */
.highlight-link:hover::before

Managing Specificity in Modular CSS

Modern CSS methodologies (like BEM) avoid specificity issues through naming conventions:

/* BEM naming convention */
.block__element--modifier {
  color: red;
}

Reset and Normalize Styles

Reset stylesheets typically use low-specificity selectors for easy overriding:

/* Low-specificity reset */
html, body, div, span, h1, h2, h3, p {
  margin: 0;
  padding: 0;
}

Impact of Stacking Context

In some cases, stacking context affects style display even when specificity is equal:

.parent {
  position: relative;
  z-index: 1;
}

.child {
  position: absolute;
  z-index: 9999; /* Still constrained by parent's stacking context */
}

Specificity in Media Queries

Media queries don't change selector specificity; they only conditionally apply styles:

/* Same specificity, latter definition wins */
@media (min-width: 768px) {
  .container { width: 750px; }
}

@media (min-width: 992px) {
  .container { width: 970px; }
}

Specificity of Custom Properties

CSS variables (custom properties) follow standard specificity rules:

:root {
  --main-color: blue;
}

.component {
  --main-color: red; /* Overrides root variable */
  color: var(--main-color);
}

Specificity in Shadow DOM

In Shadow DOM, external styles generally don't affect components unless explicitly declared:

class MyElement extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
      <style>
        /* Component styles */
        p { color: red; }
      </style>
      <p>Shadow DOM content</p>
    `;
  }
}

Specificity of Animations and Transitions

Animation styles override regular styles even with lower specificity:

.box {
  background: red; /* Weight: 0,0,1,0 */
  animation: changeColor 2s infinite;
}

@keyframes changeColor {
  50% {
    background: blue; /* Overrides original style during animation */
  }
}

The content Property in Pseudo-Elements

The content property has unique specificity behavior:

.tooltip::after {
  content: "Default tooltip"; /* Can be overridden by higher-specificity rules */
}

.tooltip.special::after {
  content: "Special tooltip"; /* Overrides the above content */
}

Specificity of User Agent Styles

Browser default styles have the lowest specificity and are usually overridden by author styles:

/* Override browser default link styles */
a {
  color: #0066cc;
  text-decoration: none;
}

Balancing Selector Performance and Specificity

When writing CSS, balance selector performance and specificity:

/* Balanced performance and specificity */
.product-list > .item > .title {
  font-size: 1.2em;
}

/* Better performance than below while maintaining reasonable specificity */
.product-list .item .title {
  font-size: 1.2em;
}

Specificity of Dynamic Class Names

Class names added dynamically via JavaScript follow the same specificity rules:

<style>
  .active { color: red; }
  .highlight { color: yellow; }
</style>

<p id="text">Example text</p>

<script>
  document.getElementById('text').classList.add('active', 'highlight');
  // Final color is yellow because both classes have equal weight, latter wins
</script>

Specificity of Multiple Class Selectors

Combining multiple class selectors increases weight:

/* Weight: 0,0,1,0 */
.btn {
  padding: 8px 16px;
}

/* Weight: 0,0,2,0 */
.btn.primary {
  background: blue;
}

Weight of Adjacent Sibling Selectors

Adjacent sibling selector (+) and general sibling selector (~) don't affect weight calculation:

/* Weight: 0,0,1,1 */
h2 + p {
  margin-top: 0;
}

/* Weight: 0,0,1,1 */
h2 ~ p {
  color: gray;
}

Weight of Negation Pseudo-Class

The :not() pseudo-class itself doesn't add weight, but selectors inside it do:

/* Weight: 0,0,1,1 (from input and :not) */
input:not(.disabled) {
  opacity: 1;
}

Conflicts Between Global and Component Styles

In component-based development, global styles may accidentally affect components:

/* Global styles - may accidentally affect components */
button {
  border-radius: 4px;
}

/* Component styles - need sufficient specificity */
.my-component button {
  border-radius: 0;
}

Specificity Visualization Tools

Some tools can help visualize selector specificity:

# Use specific tools to analyze CSS selectors
css-specificity-analyser styles.css

Future CSS Changes

New CSS features like :is() and :where() will change specificity calculation:

/* Selectors in :where() don't contribute to weight */
:where(.container) .item {
  color: blue; /* Weight: 0,0,0,1 */
}

/* Selectors in :is() take the highest weight */
:is(#main, .container) .item {
  color: red; /* Weight: 0,1,0,1 (from #main) */
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.