CSS FundamentalsBeginner8 min02 / 9

CSS Selectors

Learn how to aim CSS styles at exactly the right elements on a page using element, class, id, grouping, descendant, pseudo-class, and attribute selectors.

CSS is a two-part language. The first part is the style itself — color: red, font-size: 18px. The second part, and arguably the more powerful one, is the selector: the instruction that tells the browser which elements on the page should receive that style. Write the wrong selector and your styles go nowhere. Write the right one and you can reach any element with surgical precision. This lesson is all about learning to aim.

Every CSS rule follows the same shape: a selector, then a block of declarations in curly braces. The selector says who gets the styles; the declarations say what those styles are.

#Element Selectors — the Wide Net

The simplest selector is the element selector: write a tag name and every element of that type on the page gets the styles. This is ideal for page-wide defaults — "all my paragraphs should look like this".

Element selectors cast a wide net — they match every element of that tag type, anywhere on the page.
h1 {
  font-size: 2rem;
  color: #1a1a2e;
}

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

#Class Selectors (.) and ID Selectors (#)

When you need to target only some elements — not all paragraphs, just specific ones — you use a class selector. Add a class attribute to your HTML elements, then prefix the class name with a dot (.) in CSS. An element can carry multiple classes at once: class="card featured".

ID selectors (#name) target a single, unique element on the page. An ID must appear only once per page. Use them for one-of-a-kind landmarks like a main navigation bar or a hero section.

Dot for class, hash for ID. Classes are reusable; IDs are unique per page.
/* Class selector: any element with class='badge' */
.badge {
  background-color: #4f46e5;
  color: white;
  padding: 3px 10px;
  border-radius: 999px;
}

/* ID selector: the one element with id='page-title' */
#page-title {
  font-size: 2.5rem;
  color: #1a1a2e;
}
Watch out

Prefer classes over IDs for styling

ID selectors carry very high specificity — CSS's way of deciding which rule wins when two rules target the same element. That high power makes your styles hard to override later. Most developers style almost everything with classes and reserve IDs for page anchors (href="#section") and JavaScript. The practical rule: if you ever need the same style on more than one element, use a class.

Think of it like

Descendant selectors are like a mailing address

An address goes from general to specific: Country → City → Street → House. Writing nav a in CSS works the same way — "find all <a> elements that live anywhere inside a <nav> element". You name the container first, then the thing you want inside it. The space between them is what creates that ancestor–descendant relationship.

Commas group selectors; a space creates a descendant relationship.
/* Grouping: apply the same rule to multiple selectors */
h1, h2, h3 {
  font-family: Georgia, serif;
  color: #1a1a2e;
}

/* Descendant: only <a> tags that are inside <nav> */
nav a {
  color: white;
  text-decoration: none;
}

Pseudo-classes style an element based on its state — hovered, focused, visited. Append them with a colon (:). Two of the most useful: :hover fires when the mouse is over an element; :focus fires when it receives keyboard focus (vital for accessibility).

Attribute selectors use square brackets to target elements by their HTML attributes: input[type="text"] matches only text inputs, leaving checkboxes and radio buttons untouched.

Pseudo-classes respond to user interaction; attribute selectors filter by HTML attribute values.
/* :hover changes the button colour on mouse-over */
button:hover {
  background-color: #4338ca;
}

/* :focus gives keyboard users a visible focus ring */
button:focus {
  outline: 3px solid #a5b4fc;
  outline-offset: 2px;
}

/* Attribute selector: only text-type inputs */
input[type="text"] {
  border: 1px solid #ccc;
  padding: 8px 12px;
  border-radius: 4px;
}
Quick check

You have ten <li> elements on a page and you want exactly three of them to display a bold, red label style. Which selector type is the best choice?

Common mistake

CSS reads all matching rules — order and specificity decide the winner

When two rules target the same element and set the same property, CSS does not simply use the last one. It first checks specificity: ID selectors beat class selectors, which beat element selectors. Only if specificity is equal does the later rule win. This is why an element selector rule placed at the bottom of your file will still lose to an ID selector at the top. Understanding this saves hours of debugging.

Key takeaways

  • Element selectors (h1, p) target every element of that tag type — best for page-wide defaults.
  • Class selectors (.name) target any element carrying that class — the most flexible and commonly used selector type.
  • ID selectors (#name) target one unique element; use them sparingly because their high specificity makes styles hard to override.
  • Grouping (h1, h2, h3) avoids repeated declarations; descendant selectors (nav a) target elements nested inside a specific ancestor.
  • Pseudo-classes (:hover, :focus) style elements by state; attribute selectors ([type='text']) filter by HTML attribute values.
Practice challenges
Test yourself · earn XP
0/4
Fill in the blank#1

Fill in the selector so this rule targets any element carrying class="badge".

 {
  background-color: #4f46e5;
  color: white;
  border-radius: 999px;
}
Fill in the blank#2

Complete this rule so it matches only <a> elements that live inside a <nav> element.

nava {
  color: white;
  text-decoration: none;
}
Fix the bug#3

This rule is meant to style the single element with id="page-title", but nothing changes. What's wrong?

fix-bug
.page-title {
  font-size: 2.5rem;
  color: #1a1a2e;
}
Predict the output#4

Both rules target the same element (it has id="cta" and class="btn"). What color will its text be?

predict-output
#cta {
  color: white;
}

.btn {
  color: black;
}
Your turn
Practice exercise

Given the HTML below, write CSS to accomplish four things: (1) Make all paragraphs have a line-height of 1.7 and a colour of #333. (2) Give elements with the class 'badge' a pill shape with a blue background and white text. (3) Style the element with id 'page-title' to be large and dark. (4) Make the badge turn darker blue when hovered.

Try it live — edit the code and hit Run to see it rendered:

solution.css · editable