CSS Selectors and Specificity

CSS Selectors and Specificity

CSS selectors are the foundation of styling web pages. They determine which HTML elements get styled and how. Understanding selectors and specificity is crucial for writing maintainable CSS. This tutorial covers the different types of selectors and how specificity works to resolve style conflicts.

What are CSS Selectors?

Selectors are patterns that match HTML elements on a page. When a selector matches an element, the CSS rules inside the curly braces {} are applied to that element.

/* Selector */
h1 {
  /* Declaration */
  color: blue;
  font-size: 24px;
}

Basic Selectors

Element Selector (Type Selector)

Selects all elements of a specific type.

p {
  color: #333;
}

h1, h2, h3 {
  font-family: Arial, sans-serif;
}

Class Selector

Selects elements with a specific class attribute. Use a dot (.) followed by the class name.

.highlight {
  background-color: yellow;
}

.btn-primary {
  background-color: blue;
  color: white;
}

ID Selector

Selects a single element with a specific id attribute. Use a hash (#) followed by the id.

#header {
  background-color: #f0f0f0;
}

#nav-menu {
  list-style: none;
}

Universal Selector

Selects all elements. Use an asterisk (*).

* {
  margin: 0;
  padding: 0;
}

Attribute Selectors

Select elements based on their attributes.

/* Elements with a title attribute */
[title] {
  border-bottom: 1px dotted;
}

/* Elements with href containing "example.com" */
[href*="example.com"] {
  color: green;
}

/* Input elements with type="text" */
input[type="text"] {
  border: 1px solid #ccc;
}

/* Links starting with "https" */
a[href^="https"] {
  background: url(lock.png) no-repeat left;
}

Combinator Selectors

Descendant Selector (Space)

Selects all descendants of a parent element.

/* All p elements inside div elements */
div p {
  color: red;
}

/* All li elements inside ul elements inside nav */
nav ul li {
  display: inline-block;
}

Child Selector (>)

Selects direct children of a parent element.

/* Direct children p of div */
div > p {
  font-weight: bold;
}

/* Direct children li of ul */
ul > li {
  margin-left: 20px;
}

Adjacent Sibling Selector (+)

Selects the immediately following sibling.

/* p elements that come directly after h1 */
h1 + p {
  margin-top: 0;
}

/* li elements that come directly after another li */
li + li {
  border-top: 1px solid #eee;
}

General Sibling Selector (~)

Selects all following siblings of the same type.

/* All p elements that follow h1 (not necessarily immediately) */
h1 ~ p {
  color: gray;
}

Pseudo-Class Selectors

Pseudo-classes select elements in a specific state.

Link States

a:link {
  color: blue;
}

a:visited {
  color: purple;
}

a:hover {
  color: red;
}

a:active {
  color: orange;
}

Form States

input:focus {
  border-color: blue;
  outline: none;
}

input:valid {
  border-color: green;
}

input:invalid {
  border-color: red;
}

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

Structural Pseudo-Classes

/* First child */
li:first-child {
  font-weight: bold;
}

/* Last child */
li:last-child {
  margin-bottom: 0;
}

/* nth-child */
li:nth-child(odd) {
  background-color: #f9f9f9;
}

li:nth-child(even) {
  background-color: #fff;
}

/* Every 3rd child starting from 1 */
li:nth-child(3n+1) {
  color: blue;
}

Other Useful Pseudo-Classes

/* Elements that don't match a selector */
div:not(.special) {
  opacity: 0.8;
}

/* Elements that have no children */
.empty:empty {
  display: none;
}

/* Elements that are the only child */
:only-child {
  text-align: center;
}

Pseudo-Element Selectors

Pseudo-elements create virtual elements that don’t exist in the HTML.

/* First line of text */
p::first-line {
  font-weight: bold;
  color: blue;
}

/* First letter of text */
p::first-letter {
  font-size: 2em;
  float: left;
  margin-right: 5px;
}

/* Content before element */
.quote::before {
  content: '"';
  font-size: 2em;
}

/* Content after element */
.quote::after {
  content: '"';
  font-size: 2em;
}

/* Selection styling */
::selection {
  background-color: yellow;
  color: black;
}

Understanding Specificity

Specificity determines which CSS rule applies when multiple rules target the same element. It’s calculated using a point system:

  • Inline styles: 1000 points
  • ID selectors: 100 points each
  • Class, attribute, pseudo-class selectors: 10 points each
  • Element, pseudo-element selectors: 1 point each

Examples

/* Specificity: 0,0,0,1 (1 element) */
p {
  color: red;
}

/* Specificity: 0,0,1,0 (1 class) */
.text {
  color: blue;
}

/* Specificity: 0,1,0,0 (1 ID) */
#header {
  color: green;
}

/* Specificity: 0,1,1,1 (1 ID, 1 class, 1 element) */
#header .text p {
  color: purple;
}

The rule with the highest specificity wins. If specificity is equal, the last rule in the CSS wins.

Specificity in Action

<div id="header">
  <p class="text">This paragraph has multiple styles applied</p>
</div>
/* Specificity: 0,0,0,1 */
p {
  color: red;
}

/* Specificity: 0,0,1,0 */
.text {
  color: blue;
}

/* Specificity: 0,1,0,0 - This wins! */
#header p {
  color: green;
}

/* Inline style - Highest specificity */
<p class="text" style="color: purple;">This paragraph...</p>

!important Declaration

The !important declaration overrides all other declarations, even inline styles. Use sparingly as it breaks the natural cascade.

p {
  color: red !important; /* This will always apply */
}

Best Practices

  1. Avoid over-specificity: Don’t chain too many selectors
  2. Use classes for styling: Prefer classes over IDs for reusable styles
  3. Avoid !important: Only use when absolutely necessary
  4. Organize CSS logically: Group related selectors together
  5. Comment your CSS: Explain complex selectors

Common Selector Patterns

BEM (Block Element Modifier)

/* Block */
.card { }

/* Element */
.card__title { }
.card__content { }

/* Modifier */
.card--featured { }
.card__title--large { }

Component-Based CSS

/* Component namespace */
.btn { }
.btn--primary { }
.btn--secondary { }
.btn--large { }

Debugging Specificity Issues

Use browser developer tools to inspect specificity:

  1. Open DevTools (F12)
  2. Select an element
  3. Check the “Computed” tab
  4. Look at which rules are crossed out (overridden)

Complete Example

<!DOCTYPE html>
<html>
<head>
  <style>
    /* Base styles */
    body {
      font-family: Arial, sans-serif;
      line-height: 1.6;
    }

    /* Element selectors */
    h1, h2, h3 {
      color: #333;
      margin-bottom: 10px;
    }

    /* Class selectors */
    .highlight {
      background-color: #ffff99;
      padding: 5px;
    }

    .btn {
      display: inline-block;
      padding: 10px 20px;
      text-decoration: none;
      border-radius: 5px;
    }

    .btn-primary {
      background-color: #007bff;
      color: white;
    }

    /* ID selector */
    #header {
      background-color: #f8f9fa;
      padding: 20px;
      border-bottom: 1px solid #dee2e6;
    }

    /* Descendant selectors */
    #header h1 {
      margin: 0;
      color: #495057;
    }

    /* Pseudo-classes */
    .btn:hover {
      opacity: 0.8;
    }

    .btn:active {
      transform: translateY(1px);
    }

    /* Attribute selectors */
    input[type="text"] {
      width: 100%;
      padding: 8px;
      border: 1px solid #ccc;
      border-radius: 4px;
    }

    input[type="text"]:focus {
      border-color: #007bff;
      outline: none;
    }

    /* Structural pseudo-classes */
    li:first-child {
      font-weight: bold;
    }

    li:last-child {
      margin-bottom: 0;
    }

    /* Pseudo-elements */
    p::first-letter {
      font-size: 1.2em;
      font-weight: bold;
      color: #007bff;
    }

    .quote::before,
    .quote::after {
      content: '"';
      font-size: 1.5em;
      color: #6c757d;
    }
  </style>
</head>
<body>
  <div id="header">
    <h1>CSS Selectors Tutorial</h1>
  </div>
  
  <p class="quote">This is a highlighted paragraph with special styling.</p>
  
  <a href="#" class="btn btn-primary">Primary Button</a>
  
  <input type="text" placeholder="Enter your name">
  
  <ul>
    <li>First item (bold)</li>
    <li>Second item</li>
    <li>Third item</li>
    <li>Last item (no bottom margin)</li>
  </ul>
</body>
</html>

Summary

CSS selectors are powerful tools for targeting HTML elements. Remember:

Selector TypeSyntaxSpecificity Points
Universal*0
Elementp1
Class.class10
Attribute[attr]10
Pseudo-class:hover10
ID#id100
Inline stylestyle=""1000

Mastering selectors and understanding specificity will help you write cleaner, more maintainable CSS.


External Resources:

Related Tutorials:

  • Learn about CSS positioning here to understand layout after selecting elements.
  • Check out CSS Flexbox here for modern layout techniques.
Last updated on