The priority calculation rules of 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:
!important
declarations- Inline styles (style attribute)
- ID selectors
- Class selectors, attribute selectors, and pseudo-classes
- 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:
- Use browser developer tools to inspect applied styles
- Check which rules are overridden (usually shown with strikethrough)
- 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
上一篇:CSS的层叠与继承机制
下一篇:CSS的注释方法