← Back to tutorials

CSS Syntax, Selectors & Specificity

Learn about CSS syntax, selectors, and how specificity affects the styling of elements.

CSS Selectors Overview

CSS selectors are patterns used to select the HTML elements you want to style. They are one of the most fundamental concepts in CSS and allow you to target elements with precision.

<div class="container">
  <p class="intro">Hello World</p>
</div>
.intro {
  color: blue;
}
Why Selectors Matter:
  • Precision: Target specific elements without affecting others
  • Maintainability: Write cleaner, more organized CSS
  • Efficiency: Reduce the amount of CSS needed
  • Power: Create complex styling relationships between elements
Selector Types:

CSS selectors can be categorized into several types:

  • Basic Selectors: Element, Class, ID, Universal
  • Combinator Selectors: Descendant, Child, Adjacent Sibling, General Sibling
  • Pseudo-class Selectors: :hover, :focus, :nth-child()
  • Pseudo-element Selectors: ::before, ::after, ::first-line
  • Attribute Selectors: [attribute], [attribute=value]

Basic Selectors

Basic selectors are the foundation of CSS targeting. They include element, class, ID, and universal selectors.

Selector Example Description Specificity
* * { margin: 0; } Selects all elements 0-0-0
element p { color: blue; } Selects all <p> elements 0-0-1
.class .intro { font-size: 18px; } Selects all elements with class="intro" 0-1-0
#id #header { background: gray; } Selects the element with id="header" 1-0-0
Examples in Practice:
Element Selector
/* Targets all paragraph elements */
p {
    line-height: 1.6;
    margin-bottom: 1em;
}
Class Selector
/* Targets all elements with class="button" */
.button {
    padding: 10px 20px;
    background-color: #4e73df;
    color: white;
    border: none;
    border-radius: 4px;
}
ID Selector
/* Targets the element with id="main-nav" */
#main-nav {
    background-color: #333;
    padding: 15px;
}
Best Practice: Use classes for styling that might be reused, and reserve IDs for unique elements that need JavaScript hooks or anchor links.

Combinator Selectors

Combinator selectors allow you to target elements based on their relationship to other elements in the document tree.

Selector Example Description
(space) div p Descendant selector - selects all <p> inside <div>
> div > p Child selector - selects direct <p> children of <div>
+ div + p Adjacent sibling - selects <p> immediately after <div>
~ div ~ p General sibling - selects all <p> that are siblings of <div>
Combinator Examples:
Descendant Selector
/* Targets any paragraph inside a div, at any nesting level */
div p {
    color: blue;
}
Child Selector
/* Targets only direct child paragraphs of a div */
div > p {
    font-weight: bold;
}
Adjacent Sibling Selector
/* Targets only the paragraph immediately after a div */
div + p {
    margin-top: 20px;
}
Combinator Tips:
  • Use descendant selectors sparingly as they can impact performance
  • Child selectors (>) are more specific and performant than descendant selectors
  • Adjacent sibling selectors are useful for styling elements that follow specific elements

Pseudo-class & Pseudo-element Selectors

Pseudo-selectors allow you to style elements based on their state or to style specific parts of elements.

Common Pseudo-classes:
Selector Example Description
:hover a:hover Selects links on mouse hover
:focus input:focus Selects input element that has focus
:first-child p:first-child Selects first <p> element among its siblings
:nth-child(n) li:nth-child(odd) Selects every odd <li> element
:not(selector) div:not(.special) Selects all <div> elements except those with class="special"
Common Pseudo-elements:
Selector Example Description
::before p::before Inserts content before <p> element
::after p::after Inserts content after <p> element
::first-line p::first-line Selects the first line of <p> element
::selection ::selection Selects the portion of an element selected by user
Pseudo-selector Examples:
Pseudo-class Example
/* Style links on hover and focus */
a:hover, a:focus {
    color: #e74a3b;
    text-decoration: underline;
}

/* Style every other table row */
tr:nth-child(even) {
    background-color: #f8f9fc;
}
Pseudo-element Example
/* Add quotation marks before blockquotes */
blockquote::before {
    content: "“";
    font-size: 2em;
    color: #4e73df;
}

/* Style the first line of paragraphs */
p::first-line {
    font-weight: bold;
    color: #2e59d9;
}

Attribute Selectors

Attribute selectors allow you to target elements based on their attributes or attribute values.

Selector Example Description
[attribute] [target] Selects elements with a target attribute
[attribute=value] [target="_blank"] Selects elements with target="_blank"
[attribute~=value] [title~=flower] Selects elements with title containing "flower"
[attribute|=value] [lang|=en] Selects elements with lang starting with "en"
[attribute^=value] a[href^="https"] Selects <a> with href starting with "https"
[attribute$=value] a[href$=".pdf"] Selects <a> with href ending with ".pdf"
[attribute*=value] a[href*="w3schools"] Selects <a> with href containing "w3schools"
Attribute Selector Examples:
Basic Attribute Selection
/* Style all elements with a title attribute */
[title] {
    border-bottom: 1px dotted #ccc;
}

/* Style external links (starting with http) */
a[href^="http"]::after {
    content: " ↗";
}
Advanced Attribute Selection
/* Style PDF links */
a[href$=".pdf"]::before {
    content: "📄 ";
}

/* Style email links */
a[href^="mailto:"]::before {
    content: "✉️ ";
}

/* Style required form fields */
input[required] {
    border-left: 3px solid #e74a3b;
}
Pro Tip: Attribute selectors are incredibly powerful for styling forms, links, and custom data attributes without needing extra classes.

CSS Specificity Basics

Specificity is the algorithm browsers use to determine which CSS property values are the most relevant to an element and will be applied.

Highest
Inline Styles
style attribute
High
ID Selectors
#id
Medium
Class Selectors
.class, [attr], :pseudo
Low
Element Selectors
p, div, h1
Lowest
Universal Selector
*
Specificity Examples:
This element has multiple conflicting styles
/* Specificity: 0-0-1 */
div {
    background-color: blue;
}

/* Specificity: 0-1-0 */
.conflict-element {
    background-color: green;
}

/* Specificity: 1-0-0 */
#specificityExample1 {
    background-color: red;
}

Result: The background will be red because ID selectors have higher specificity than class or element selectors.

Important Rules:
  • When selectors have equal specificity, the last rule in the CSS wins
  • The !important rule overrides all previous styling rules
  • Inline styles have higher specificity than styles in external or internal stylesheets

Specificity Calculation

Specificity is calculated using a three-number system: (a-b-c), where:

  • a: Number of ID selectors
  • b: Number of class, attribute, and pseudo-class selectors
  • c: Number of element and pseudo-element selectors
Specificity Calculation Examples:
Selector Specificity Calculation
* 0-0-0 No IDs, classes, or elements
p 0-0-1 One element selector
.intro 0-1-0 One class selector
#header 1-0-0 One ID selector
ul#nav li.active a 1-1-3 One ID, one class, three elements
input[type="text"] 0-1-1 One attribute, one element
a:hover 0-1-1 One pseudo-class, one element
Interactive Specificity Calculator
0
IDs
0
Classes
0
Elements

Specificity: 0-0-0

Specificity Rules & Best Practices

Understanding and properly managing specificity is crucial for writing maintainable CSS.

Key Specificity Rules:
  1. Cascade Order: When specificity is equal, the last rule declared wins
  2. Inheritance: Some properties inherit values from parent elements
  3. !important Rule: Overrides all specificity calculations (use sparingly!)
  4. Inline Styles: Have higher specificity than any selector (except !important)
Specificity Conflict Example:
Watch what happens when styles conflict!
Applied Styles (in priority order):
  • No styles applied yet
Best Practices for Managing Specificity:
  • Use classes for most styling - They have moderate specificity and are reusable
  • Avoid using IDs for styling - They create specificity issues that are hard to override
  • Keep specificity low - This makes your CSS easier to maintain and override
  • Avoid !important - It breaks the natural cascade and creates maintenance problems
  • Use methodologies like BEM - They provide a structured approach to naming that avoids specificity issues
Avoid the Specificity War: When you find yourself constantly increasing specificity to override previous styles, it's a sign that you need to refactor your CSS architecture.

Interactive Selector & Specificity Demo

Test different CSS selectors and see how they affect elements in real-time:

0-0-0
Test Elements:
#special
[data-type]
.test-element
.test-element.special
Nested .test-element
Generated CSS:
/* No CSS applied yet */