Skip to content

CSS Selectors

CSS selectors define which HTML elements receive styles. In this tutorial, you will learn element selectors, class selectors, ID selectors, grouping selectors, combinators, attribute selectors, pseudo-classes, pseudo-elements, specificity, examples, best practices, and common mistakes.

What Are CSS Selectors?

CSS selectors are patterns used to target HTML elements. Once an element matches a selector, the browser applies the CSS declarations inside that rule.

selector {
  property: value;
}

For example, the following selector targets all paragraph elements.

p {
  color: #333333;
  line-height: 1.6;
}

Why CSS Selectors Are Important

  • Selectors control which elements are styled.
  • Good selectors make CSS reusable and maintainable.
  • Simple selectors reduce debugging problems.
  • Selectors affect CSS specificity and override behavior.
  • Reusable selectors support design systems and component libraries.
  • Clean selectors improve long-term project organization.

CSS Selectors Cheatsheet

The following table summarizes the most commonly used CSS selectors with examples.

Selector Type Example Purpose
Element Selector p Selects all matching HTML elements.
Class Selector .card Selects elements with a specific class.
ID Selector #header Selects one unique element with a specific ID.
Universal Selector * Selects all elements.
Grouping Selector h1, h2, h3 Applies the same styles to multiple selectors.
Descendant Selector .card p Selects matching elements inside another element.
Child Selector .menu > li Selects direct children only.
Adjacent Sibling h2 + p Selects the next sibling immediately after another element.
General Sibling h2 ~ p Selects matching siblings after another element.
Attribute Selector input[type="email"] Selects elements based on attributes.
Pseudo-class a:hover Selects elements in a specific state.
Pseudo-element p::first-line Styles a specific part of an element.

Element Selector

An element selector targets all matching HTML tags.

h1 {
  color: #0d6efd;
}

p {
  line-height: 1.6;
}

Use element selectors for base styles like headings, paragraphs, lists, and body text.

Class Selector

A class selector starts with a dot and targets elements that contain a matching class attribute.

.card {
  padding: 1.5rem;
  border: 1px solid #dee2e6;
  border-radius: 0.75rem;
}

HTML Example

<article class="card">
  <h2>CSS Selectors</h2>
  <p>Learn selector basics.</p>
</article>

Classes are the best choice for reusable components and design patterns.

ID Selector

An ID selector starts with a hash symbol and targets one unique element.

#main-header {
  background-color: #212529;
  color: #ffffff;
}

HTML Example

<header id="main-header">
  Website Header
</header>

IDs are useful for anchors and unique elements, but classes are usually better for reusable styling.

Universal Selector

The universal selector targets all elements.

* {
  box-sizing: border-box;
}

Use the universal selector carefully because it applies broadly.

Grouping Selectors

Grouping selectors allow multiple selectors to share the same declarations.

h1,
h2,
h3 {
  line-height: 1.2;
  margin-bottom: 1rem;
}

This reduces duplicate CSS and keeps related styles together.

Descendant Selector

A descendant selector targets elements inside another element, at any nesting level.

.article-content p {
  margin-bottom: 1rem;
}

This targets all paragraphs inside .article-content.

Child Selector

A child selector targets only direct children.

.menu > li {
  list-style: none;
}

This targets only li elements that are direct children of .menu.

Sibling Selectors

Sibling selectors target elements that share the same parent.

Adjacent Sibling Selector

h2 + p {
  font-size: 1.125rem;
}

This targets the first paragraph immediately after an h2.

General Sibling Selector

h2 ~ p {
  color: #495057;
}

This targets all paragraphs after an h2 that share the same parent.

Attribute Selectors

Attribute selectors target elements based on attributes or attribute values.

input[type="email"] {
  border-color: #0d6efd;
}

a[target="_blank"] {
  text-decoration-style: dotted;
}
Selector Matches
[disabled] Elements with a disabled attribute.
[type="email"] Elements where type equals email.
[href^="https"] Links where href starts with https.
[href$=".pdf"] Links where href ends with .pdf.
[class*="btn"] Elements where class contains btn.

Pseudo-class Selectors

Pseudo-classes target elements in a specific state.

a:hover {
  text-decoration-thickness: 0.12em;
}

button:focus-visible {
  outline: 3px solid #111111;
  outline-offset: 3px;
}

input:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

Common pseudo-classes include :hover, :focus, :focus-visible, :disabled, :checked, :first-child, :last-child, and :not().

Pseudo-element Selectors

Pseudo-elements style a specific part of an element.

p::first-line {
  font-weight: 700;
}

.card::before {
  content: "";
  display: block;
  height: 4px;
  background-color: #0d6efd;
}

Common pseudo-elements include ::before, ::after, ::first-line, ::first-letter, ::marker, and ::selection.

Modern CSS Selectors: :not(), :is(), :where(), and :has()

Modern CSS provides powerful selector helpers that make complex selectors cleaner.

.button:not(.disabled) {
  cursor: pointer;
}

:is(h1, h2, h3) {
  line-height: 1.2;
}

:where(header, main, footer) a {
  text-underline-offset: 0.2em;
}

.card:has(img) {
  display: grid;
  gap: 1rem;
}
  • :not() excludes matching elements.
  • :is() groups selector options.
  • :where() groups selectors with zero specificity.
  • :has() selects elements based on their children or content.

CSS Selectors and Specificity

Specificity decides which CSS rule wins when multiple rules target the same element.

Selector Specificity Level Example
Element Low p
Class Medium .text-primary
ID High #hero
Inline Style Very High style="color: red;"
!important Override Rule color: red !important;
p {
  color: black;
}

.text-primary {
  color: blue;
}

#intro {
  color: red;
}

In general, avoid high specificity unless it is truly needed.

CSS Selector Performance

Modern browsers handle selectors efficiently, but simple selectors are easier to maintain and debug. Avoid deeply nested selectors that depend on fragile HTML structure.

Less Maintainable

body main section article div.card ul li a span {
  color: #0d6efd;
}

Better

.card-link {
  color: #0d6efd;
}

Short, meaningful class selectors are usually better for components.

CSS Selector Best Practices

  • Use class selectors for reusable components.
  • Use element selectors for global base styles.
  • Use ID selectors sparingly.
  • Avoid deeply nested selectors.
  • Avoid overusing !important.
  • Use grouping selectors to reduce duplicate code.
  • Use meaningful class names.
  • Keep specificity low and predictable.
  • Use pseudo-classes for states like hover, focus, and disabled.
  • Test selectors in DevTools when debugging.

Common CSS Selector Mistakes

  • Forgetting the dot before class selectors.
  • Forgetting the hash before ID selectors.
  • Using IDs for reusable component styles.
  • Writing selectors that are too specific.
  • Using selectors that break when HTML structure changes.
  • Overusing universal selectors.
  • Depending too much on element selectors in large projects.
  • Using !important instead of fixing specificity.

Incorrect

card {
  padding: 1rem;
}

Correct

.card {
  padding: 1rem;
}

CSS Selectors, SEO, and Accessibility

Selectors do not directly affect search rankings, but well-structured CSS supports readable content, responsive layouts, accessible focus states, and maintainable design.

a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 3px solid #111111;
  outline-offset: 3px;
}
  • Use selectors to keep focus states visible.
  • Avoid hiding important content with CSS.
  • Use responsive selectors and media queries for mobile layouts.
  • Keep visual styles consistent across reusable components.
  • Do not rely on CSS alone to create meaningful HTML structure.

Key Takeaways

  • CSS selectors target HTML elements for styling.
  • Common selectors include element, class, ID, universal, group, and attribute selectors.
  • Pseudo-classes target element states like hover, focus, checked, and disabled.
  • Pseudo-elements style parts of elements like first line, markers, before, and after.
  • Specificity decides which rule wins when multiple selectors target the same element.
  • Simple, reusable selectors are easier to maintain and debug.

Pro Tip

For most real projects, use class selectors for components, element selectors for base styles, and ID selectors only when uniqueness is required.