Skip to main content

Selectors

A selector is the first part of every CSS rule. It tells the browser which HTML elements the rule applies to. Master selectors and you control exactly where your styles land.

Element selectors

The simplest selector targets elements by their tag name:

h1 {
color: navy;
}

p {
font-size: 18px;
}

li {
margin-bottom: 8px;
}

This styles every <h1>, every <p>, and every <li> on the page. Element selectors are broad -- they do not distinguish between different paragraphs or different list items.

Class selectors

A class selector targets elements that have a specific class attribute. Class names start with a dot (.) in CSS:

<p class="intro">Welcome to the site.</p>
<p>This is a regular paragraph.</p>
<p class="intro">Another intro paragraph.</p>
.intro {
font-size: 20px;
font-weight: bold;
color: #1a1a2e;
}

Only the two paragraphs with class="intro" get styled. The regular paragraph is unaffected.

Key points about classes:

  • An element can have multiple classes: <p class="intro highlight">
  • Many elements can share the same class
  • Class names are case-sensitive: .Intro and .intro are different
  • Use lowercase and hyphens for class names: .main-content, .nav-link, .error-message

Tip: Classes are the workhorse of CSS. You will use them far more than any other selector type. When in doubt, use a class.

ID selectors

An ID selector targets the element with a specific id attribute. IDs start with a hash (#) in CSS:

<header id="site-header">
<h1>My Website</h1>
</header>
#site-header {
background-color: #1a1a2e;
color: white;
padding: 20px;
}

Important rules for IDs:

  • An ID must be unique on the page -- only one element can have a given ID
  • IDs have higher specificity than classes (we cover specificity in chapter 14)
  • Prefer classes over IDs for styling -- IDs are better reserved for JavaScript hooks and anchor links

Note: Many experienced developers avoid ID selectors in CSS entirely. Classes give you the same targeting power without the specificity issues. We mention IDs so you recognise them in other people's code.

Universal selector

The universal selector (*) targets every element on the page:

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

This is commonly used in CSS resets to remove default browser styles. We cover resets in chapter 16.

Note: The universal selector does not cause performance problems in modern browsers. The old advice to avoid * is outdated.

Grouping selectors

When multiple selectors share the same declarations, you can group them with commas:

h1,
h2,
h3 {
font-family: Arial, sans-serif;
color: #1a1a2e;
}

This is identical to writing three separate rules. Grouping just saves repetition.

You can group any selector types together:

.error,
.warning,
#alert-banner {
font-weight: bold;
padding: 12px;
border-radius: 4px;
}

Descendant selectors

A descendant selector targets elements nested inside other elements. You write the selectors separated by a space:

nav a {
color: white;
text-decoration: none;
}

This targets every <a> element that is inside a <nav> -- at any depth. It does not affect <a> elements outside the nav.

<nav>
<a href="/">Home</a> <!-- styled -->
<div>
<a href="/about">About</a> <!-- also styled (nested deeper) -->
</div>
</nav>
<a href="/contact">Contact</a> <!-- NOT styled -->

You can chain multiple levels:

main article p {
line-height: 1.8;
}

This targets <p> elements inside <article> elements inside <main>.

Tip: Keep descendant selectors short -- two or three levels at most. Long chains like div ul li a span are fragile and break when you restructure your HTML.

Child selector

The child selector (>) targets elements that are direct children -- not deeper descendants:

ul > li {
border-bottom: 1px solid #ddd;
}
<ul>
<li>Direct child -- styled</li>
<li>
Direct child -- styled
<ul>
<li>Nested li -- NOT styled (not a direct child of the outer ul)</li>
</ul>
</li>
</ul>

The child selector is more precise than the descendant selector. Use it when you want to target only the first level of nesting.

Sibling selectors

Sibling selectors target elements that share the same parent.

Adjacent sibling (+)

Targets the element immediately after another element:

h2 + p {
font-size: 20px;
color: #555;
}

This styles only the first <p> that directly follows an <h2>. It is useful for styling lead paragraphs after headings.

<h2>Section Title</h2>
<p>This paragraph is styled (immediately after h2).</p>
<p>This paragraph is NOT styled.</p>

General sibling (~)

Targets all siblings that come after an element:

h2 ~ p {
margin-left: 16px;
}

This styles every <p> that comes after an <h2> and shares the same parent -- not just the first one.

Attribute selectors

Attribute selectors target elements based on their HTML attributes:

SelectorWhat it matches
[href]Any element with an href attribute
[type="text"]Elements where type is exactly "text"
[class~="warning"]Elements whose class contains the word "warning"
[href^="https"]Elements whose href starts with "https"
[href$=".pdf"]Elements whose href ends with ".pdf"
[href*="example"]Elements whose href contains "example" anywhere

Examples:

a[href^="https"] {
color: green;
}

input[type="email"] {
border: 2px solid #4a90d9;
}

a[href$=".pdf"]::after {
content: " (PDF)";
}

Attribute selectors are especially useful for styling form elements and links without adding extra classes.

Combining selectors

You can combine selector types to be more specific. Write them without spaces to target a single element that matches all conditions:

p.intro {
font-size: 20px;
}

This targets <p> elements that also have the class intro. A <div class="intro"> would not match.

More examples:

input.large[type="text"] {
font-size: 24px;
padding: 12px;
}

a.nav-link:hover {
color: tomato;
}

Selector summary

SelectorSyntaxExampleTargets
ElementelementpAll <p> elements
Class.class.introElements with class="intro"
ID#id#headerThe element with id="header"
Universal**Every element
GroupingA, Bh1, h2All <h1> and <h2> elements
DescendantA Bnav a<a> inside <nav> (any depth)
ChildA > Bul > li<li> that is a direct child of <ul>
Adjacent siblingA + Bh2 + p<p> immediately after <h2>
General siblingA ~ Bh2 ~ pAll <p> after <h2> (same parent)
Attribute[attr][href$=".pdf"]Elements whose href ends with .pdf
CombinedA.classp.intro<p> with class intro

What you learned

  • Selectors target HTML elements for styling
  • Classes (.name) are the most common and flexible selector
  • IDs (#name) are unique per page and have high specificity -- prefer classes
  • Descendant (A B) and child (A > B) selectors target nested elements
  • Sibling selectors target elements at the same level
  • Attribute selectors target elements by their HTML attributes
  • You can combine selectors for precision and group them with commas to reduce repetition

Next step

Now that you know how to target elements, the next chapter covers the box model -- how the browser calculates the size and spacing of every element on the page.