Keywords: CSS Precedence | Selector Specificity | Style Overriding
Abstract: This article provides an in-depth exploration of CSS precedence mechanisms, covering inline styles, selector specificity, declaration order, and the role of !important rules. Through concrete code examples, it analyzes specificity calculation methods and explains the root causes of style overriding in Sass extension scenarios, offering comprehensive guidance for front-end developers.
Fundamental Principles of CSS Precedence
When multiple CSS rules target the same element, browsers employ a well-defined precedence hierarchy to determine which styles to apply. This hierarchy operates in the following order:
- Inline Styles: Styles defined directly within an HTML element's style attribute have the highest precedence and override all other style sources.
- Selector Specificity: In the absence of inline styles, browsers compare the specificity values of selectors, with higher-specificity selectors taking precedence.
- Declaration Order: When multiple rules share identical specificity, the rule declared later in the code overrides earlier declarations.
- !important Declarations: Styles marked with !important always take highest precedence regardless of other factors.
Detailed Explanation of Selector Specificity
Selector specificity forms the core of CSS precedence, calculated through a three-tier weighting system:
- ID Selectors: Highest specificity, each ID selector counts as 100 points. Example:
#mainselects<div id="main">. - Class Selectors, Attribute Selectors, and Pseudo-classes: Medium specificity, each counts as 10 points. Includes
.myclass,[href^="https:"], and:hover. - Element Selectors and Pseudo-elements: Lowest specificity, each counts as 1 point. Examples:
div,::before.
When comparing specificity of compound selectors, count selectors at each level separately:
/* Example 1: #nav ul li a:hover */
ID Selectors: 1 (#nav)
Class Selectors: 1 (:hover)
Element Selectors: 3 (ul, li, a)
Specificity Score: 100 + 10 + 3 = 113
/* Example 2: #nav ul li.active a::after */
ID Selectors: 1 (#nav)
Class Selectors: 1 (.active)
Element Selectors: 4 (ul, li, a, ::after)
Specificity Score: 100 + 10 + 4 = 114
Thus, the second selector has higher specificity and its styles will be applied preferentially.
Practical Case Analysis
Consider the user's provided code scenario:
.smallbox {
background-color: white;
height: 75px;
width: 150px;
font-size: 20px;
box-shadow: 0 0 10px #ccc;
font-family: inherit;
}
.smallbox-paysummary {
@extend .smallbox;
font-size: 10px;
}
Both classes applied in HTML:
<pre class="span12 pre-scrollable smallbox-paysummary smallbox">
Although both class selectors have identical specificity (10 points each), since .smallbox-paysummary appears after .smallbox in the CSS code, the declaration order rule causes the later font-size: 10px to override the earlier font-size: 20px, explaining why the font displays at 10px instead of 20px.
Specificity Handling in Sass Extensions
When using Sass's @extend functionality, pay special attention to the compiled CSS structure. @extend .smallbox effectively merges the .smallbox-paysummary selector with .smallbox, generating rules similar to .smallbox, .smallbox-paysummary { ... }. In this scenario, both selectors share identical specificity, making declaration order the determining factor.
Practical Recommendations for Precedence Rules
To avoid style conflicts and unexpected overrides, developers should:
- Avoid inline styles whenever possible to maintain separation of concerns.
- Design selector structures rationally, avoiding over-reliance on high-specificity selectors.
- Use !important cautiously, only when absolutely necessary.
- Maintain well-organized CSS code with related style rules grouped together.
- Establish consistent CSS coding standards in team development environments.
By thoroughly understanding CSS precedence mechanisms, developers can achieve precise control over page styling, prevent common style conflict issues, and enhance front-end development efficiency.