Mastering CSS Specificity: Understanding the Algorithm and Effective Tag Selection Methods
Let’s say ,I am working on a web development project and structured the application using html , now you should style html page. so you started styling the page , give style for the button red, button class green, and button id orange. you expect the color on screen to show green ,but you get the orange. If you get to see this kind of behavior and enable to fix ,then you need to learn the Specificity Algorithm
Specificity Algorithm : CSS is a set of rules that browsers use to determine which styles are applied to an element when multiple rules match. It's calculated based on the types of selectors used in your CSS.
1. Understanding Specificity
Specificity is represented as a four-part value:
css(A, B, C, D)
A (Inline Styles): Inline styles (e.g.,
style="color: red;"
) always have the highest specificity and are counted as1
.B (IDs): The number of
id
selectors in a rule.C (Classes, Attributes, Pseudo-classes): The number of
.class
,[attribute]
, and:pseudo-class
selectors.D (Elements, Pseudo-elements): The number of
element
and::pseudo-element
selectors.
2. How Specificity is Calculated
The specificity of a selector is based on its components:
Inline styles:
(1,0,0,0)
ID selectors:
(0,1,0,0)
Classes, attributes, pseudo-classes:
(0,0,1,0)
Element and pseudo-element selectors:
(0,0,0,1)
When comparing specificity:
Compare
A
. If equal, move toB
.If
B
is equal, move toC
.If
C
is equal, move toD
.
3. Examples of Specificity
Selector | Specificity |
* Universal | (0,0,0,0) |
div tag | (0,0,0,1) |
p::before | (0,0,0,2) |
.class class | (0,0,1,0) |
[type="text"] attribute | (0,0,1,0) |
:hover pseudo element | (0,0,1,0) |
#id id | (0,1,0,0) |
style="color: red;" inline style | (1,0,0,0) |
#id.class:hover id class pseudo all in one element | (0,1,2,0) |
div#id.class[type="text"]:hover tag id class attribute pseudo in one element | (0,1,3,1) |
4. Specificity in Combined Selectors
4.1 Multiple Selectors
When multiple selectors are combined, specificity adds up:
/* Specificity: (0,1,3,1) */
div#main.container[data-type="example"]:hover::before {
color: blue;
}
4.2 Universal Selector (*
)
The universal selector does not add to specificity:
* {
color: black; /* Specificity: (0,0,0,0) */
}
4.3 Combinators
Combinators (e.g., +
, >
, ~
) do not affect specificity:
div > p {
color: red; /* Specificity: (0,0,0,2) */
}
4.4 :not()
The :not()
pseudo-class does not add specificity for its argument:
div:not(.special) { /** it wiil not applay the css to the .specal class*/
color: green; /* Specificity: (0,0,1,1) */
}
4.5 Group Selectors
In grouped selectors, each selector is evaluated independently:
h1, #main {
color: purple; /* Specificity: (0,1,0,0) for #main, (0,0,0,1) for h1 */
}
5. Corner Cases in Specificity
5.1 Inline Styles vs. External CSS
Inline styles always win, regardless of other rules:
<div id="example" style="color: red;"></div>
5.2 !important
The !important
declaration overrides specificity rules but respects the cascade (order of appearance):
div {
color: green !important;
}
#main {
color: blue; /* Ignored because of !important */
}
5.3 CSS Variables
CSS variables inherit specificity from where they are declared:
:root {
--main-color: blue;
}
5.4 Overriding with Inheritance
Inherited properties (e.g., color
, font
) do not affect specificity:
body {
color: black; /* Inherited */
}
p {
color: green; /* Overrides inherited color */
}
5.5 Cascading with Equal Specificity
When two rules have equal specificity, the last one declared wins:
div {
color: red;
}
div {
color: blue; /* Wins due to cascade order */
}
Universal selectors (*
), combinators (+
, >
, ~
), and negation pseudo-classes (:not()
,**:**root,:hover,etc..) do not affect specificity.
Pseudo elements
pseudo-element allows you to insert content before the content of an element. It is often used for adding decorative elements or text that is not part of the document's source HTML.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pseudo-Class Examples</title>
<style>
:root{
--main-color: red;
}
/* Example for :hover */
button:hover {
background-color: lightblue;
cursor: pointer;
color:var(--main-color);
}
/* Example for :active | works on clicking */
button:active {
transform: scale(0.98);
background-color: darkblue;
color: white;
}
/* Example for :focus | on the input typing*/
input:focus {
border: 2px solid green;
outline: none;
}
/* Example for :focus-visible | used while navigating on tab button in browser */
button:focus-visible {
outline: 2px dashed red;
}
/* Example for :visited */
a:visited {
color: purple;
}
/* Example for :link */
a:link {
color: blue;
text-decoration: none;
}
</style>
</head>
<body>
<h1>Pseudo-Class Examples</h1>
<!-- Hover and Active Example -->
<button style="padding: 10px 20px; font-size: 16px;">Hover or Click Me</button>
<!-- Focus Example -->
<div style="margin: 20px 0;">
<input type="text" placeholder="Focus on me" style="padding: 10px; font-size: 16px;">
</div>
<!-- Visited and Link Example -->
<div>
<a href="https://www.example.com" target="_blank">Unvisited Link</a>
<br>
<a href="https//google.com" target="_blank">Visited Link</a>
</div>
</body>
</html>
Combinators
CSS combinators are used to define relationships between elements. They target specific elements based on their position or relationship to other elements in the document. Here’s a breakdown of combinators, their use cases, and examples with inline CSS (where possible) or embedded CSS.
1. Adjacent Sibling Combinator (+
)
- Selects an element that is immediately after another specified element.
Example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Adjacent Sibling Combinator (+)</title>
<style>
h1 + p {
color: blue;
font-style: italic;
}
</style>
</head>
<body>
<h1>This is a heading</h1>
<p>This paragraph is immediately after the heading and will be styled.</p>
<p>This paragraph is not immediately after the heading and won’t be styled.</p>
</body>
</html>
Explanation:
- The
h1 + p
rule styles only the first paragraph after the<h1>
. Other<p>
elements are not affected.
2. Child Combinator (>
)
- Selects elements that are direct children of a specified parent.
Example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Child Combinator (>)</title>
<style>
div > p {
background-color: lightgreen;
padding: 10px;
}
</style>
</head>
<body>
<div>
<p>This is a direct child of the div and will be styled.</p>
<div>
<p>This is a descendant but not a direct child and won’t be styled.</p>
</div>
</div>
</body>
</html>
Explanation:
- The
div > p
rule applies only to<p>
elements that are direct children of<div>
.
3. General Sibling Combinator (~
)
- Selects elements that are siblings of a specified element and appear after it in the DOM.
Example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>General Sibling Combinator (~)</title>
<style>
h1 ~ p {
color: darkorange;
border: 1px dashed darkorange;
padding: 5px;
}
</style>
</head>
<body>
<h1>This is a heading</h1>
<p>This paragraph is a sibling of the heading and will be styled.</p>
<p>This paragraph is another sibling and will also be styled.</p>
<div>
<p>This paragraph is inside a div and won’t be styled.</p>
</div></html>
Explanation:
- The
h1 ~ p
rule applies to all<p>
elements that are siblings of<h1>
and come after it.
Summary Table of Combinators
Combinator | Selector Syntax | Description |
Adjacent | A + B | Targets B that is immediately after A . |
Child | A > B | Targets B that is a direct child of A . |
General Sibling | A ~ B | Targets all B siblings of A that follow A . |
Universal selector
it will select every thing represented by *
Summary
1. CSS Specificity
CSS specificity determines which styles are applied to an element when multiple rules target the same element. The specificity value is calculated based on a hierarchy:
Specificity is calculated as follows:
Inline Styles: 1000
IDs: 100
Classes, Pseudo-classes, and Attribute selectors: 10
Elements (tag selectors) and Pseudo-elements: 1
Specificity Hierarchy:
Inline Styles:
style="..."
– Highest specificityIDs:
#id
Classes, Pseudo-classes, and Attribute Selectors:
.class
,:hover
,[type="text"]
Elements and Pseudo-elements:
div
,p
,::before
Example:
#main { color: red; } /* Specificity: 100 (ID) */
h1 { color: blue; } /* Specificity: 1 (Element) */
button:hover { color: green; } /* Specificity: 10 (Pseudo-class) */
2. Types of Selectors
Universal Selector (
*
): Selects all elements.* { color: red; }
Type Selector (Element Selector): Selects elements by their tag name.
p { font-size: 16px; }
Class Selector (
.
): Selects elements with a specific class..btn { background-color: blue; }
ID Selector (
#
): Selects elements with a specific ID.#header { font-weight: bold; }
Attribute Selector (
[]
): Selects elements with a specific attribute.input[type="text"] { background-color: yellow; }
Pseudo-class Selector (
:
): Selects elements in a specific state.a:hover { color: green; }
Pseudo-element Selector (
::
): Targets specific parts of elements.p::first-letter { font-size: 2em; }
Descendant Selector (space): Selects elements that are descendants of another.
div p { color: blue; }
Child Selector (
>
): Selects direct children of an element.div > p { color: red; }
Adjacent Sibling Selector (
+
): Selects an element that is immediately after a specific element.h1 + p { color: green; }
General Sibling Selector (
~
): Selects all elements that are siblings of a specific element.h1 ~ p { color: orange; }
3. CSS Combinators
Descendant (
space
): Selects all elements that are descendants of a specific element.div p { color: red; }
- Matches
<p>
inside a<div>
, regardless of depth.
- Matches
Child (
>
): Selects only direct children of a specified element.div > p { color: blue; }
- Matches
<p>
only if it's a direct child of<div>
.
- Matches
Adjacent Sibling (
+
): Selects the next sibling of a specified element.h1 + p { color: green; }
- Matches the first
<p>
that follows directly after an<h1>
.
- Matches the first
General Sibling (
~
): Selects all siblings following a specific element.h1 ~ p { color: orange; }
- Matches all
<p>
siblings after an<h1>
.
- Matches all
4. Ways to Select Elements
By Tag Name (Element Selector)
- Example:
div {}
– Selects all<div>
elements.
By Class Name
- Example:
.btn {}
– Selects all elements with classbtn
.
By ID
- Example:
#header {}
– Selects the element with the IDheader
.
By Attribute
Example:
[type="text"] {}
– Selects all elements with thetype="text"
attribute.- Example:
[href*="example"] {}
– Selects all elements whosehref
contains "example".
- Example:
By Pseudo-classes
:hover
– Selects elements when hovered.a:hover { color: green; }
:first-child
– Selects the first child of its parent.div > p:first-child { font-size: 20px; }
:last-child
– Selects the last child of its parent.div > p:last-child { font-size: 20px; }
:nth-child(n)
– Selects the nth child of a parent.div > p:nth-child(2) { font-weight: bold; }
:not()
– Excludes a specific element.div:not(.special) { color: red; }
By Pseudo-elements
::before
– Inserts content before an element.p::before { content: "Note: "; font-weight: bold; }
::after
– Inserts content after an element.p::after { content: ";"; }
::first-letter
– Styles the first letter of an element.p::first-letter { font-size: 2em; }
5. Universal Selector (*
)
Selects all elements.
* { margin: 0; padding: 0; box-sizing: border-box; }
6. Combining Selectors
Multiple Selectors: Apply the same style to multiple elements.
h1, h2, h3 { color: blue; }
Grouping Selectors: Combine similar selectors to reduce repetition.
.btn, .link { text-decoration: none; color: black; }
7. Specificity Rules Recap
Inline styles have the highest specificity.
ID selectors have a higher specificity than class, attribute, or pseudo-class selectors.
Class, attribute, and pseudo-class selectors have a higher specificity than element and pseudo-element selectors.
Specificity is calculated by adding the points for each type (e.g.,
100
for IDs,10
for classes).
8. Inheritance
Some properties are inherited by child elements, like color
and font-family
. To prevent inheritance, use inherit
or initial
values.
Inheritable properties:
color
,font-family
,line-height
, etc.Non-inheritable properties:
padding
,margin
,width
, etc.
9. Specificity Example
#header { color: red; } /* ID selector */
.btn { color: blue; } /* Class selector */
p { color: green; } /* Element selector */
If a <p>
element has both a class btn
and is inside an ID header
, the color will be red because the ID selector (#header
) has the highest specificity.
10. Cascade Order
CSS rules are applied based on:
Importance (e.g.,
!important
)Specificity (see above)
Source Order (the last defined rule takes precedence if selectors have the same specificity)
11. What is div#id.class[type="text"]:hover
?
This is a complex CSS selector combining multiple selector types to target a specific element.
Breakdown:
div
: Targets adiv
element.#id
: Matches adiv
with a specific ID..class
: Matches adiv
with a specific class.[type="text"]
: Matches adiv
that has an attributetype
with the valuetext
.:hover
: Applies styles when the user hovers over thediv
.
Full Selector Meaning:
It selects a div
that:
Has a specific
id
.Has a specific
class
.Has an attribute
type
with the value"text"
.Is hovered over by the user.
Example:
htmlCopyEdit<div id="example" class="highlight" type="text">
Hover over me!
</div>
cssCopyEditdiv#example.highlight[type="text"]:hover {
background-color: lightblue;
color: darkblue;
}
Behavior:
- When you hover over the
div
, its background turns light blue, and the text color becomes dark blue.
Why Use Complex Selectors?
Granular Targeting: Allows precise control over styles.
Contextual Styling: Targets elements based on specific states or attributes.
Avoid Clashes: Reduces the chance of accidental style overrides in large projects.
Advanced Example with Explanations
<div id="login" class="form-item" type="text">
Username
</div>
<div id="password" class="form-item" type="password">
Password
</div>
/* Specific styling for hovered text input */
div#login.form-item[type="text"]:hover {
border: 2px solid green;
}
/* General styling for all form items */
div.form-item {
padding: 10px;
background-color: #f9f9f9;
}
Explanation:
The first rule applies only to the
div
withid="login"
,class="form-item"
, andtype="text"
when hovered. It adds a green border.The second rule applies to all
div
elements with theform-item
class, giving them padding and a light background.