Skip to main content

Command Palette

Search for a command to run...

CSS Selectors 101: Targeting Elements with Precision

Published
13 min read

Introduction: The Targeting Problem

Imagine you have a classroom with 30 students and you need to give instructions:

Scenario 1: "Everyone, open your textbooks"
→ Targets: ALL students

Scenario 2: "All students wearing blue shirts, stand up"
→ Targets: Students with specific characteristic (blue shirts)

Scenario 3: "Sarah, please come to the front"
→ Targets: ONE specific student by name

CSS selectors work the same way. They let you choose which HTML elements to style.

<h1>Main Title</h1>
<p>First paragraph</p>
<p>Second paragraph</p>
<p class="highlight">Important paragraph</p>
<p id="intro">Introduction paragraph</p>

Questions CSS selectors answer:

- How do I style ALL paragraphs?
- How do I style ONLY the highlighted paragraph?
- How do I style ONLY the intro paragraph?
- How do I style the title?

Without selectors, you can't apply CSS. They're that fundamental.


Why CSS Selectors Are Needed

The Problem: Blind Styling

Imagine CSS without selectors:

/* This doesn't exist! */
color: blue;
font-size: 20px;

Questions that arise:

- Which elements turn blue?
- Which text gets bigger?
- Does it apply to everything?

Answer: We don't know! That's the problem.

The Solution: Selectors

/* NOW we know! */
p {
  color: blue;
  font-size: 20px;
}

Clear answer:

✓ All <p> elements turn blue
✓ All <p> elements get 20px font size
✓ Other elements (h1, div, etc.) are unaffected

Real-World Analogy: Postal Addresses

┌─────────────────────────────────────────────────────────────┐
│  POSTAL SYSTEM = CSS SELECTORS                              │
└─────────────────────────────────────────────────────────────┘

Letter delivery:
├── Country (USA)         → Element selector (target all <p>)
├── State (California)    → More specific
├── City (San Francisco)  → Even more specific
├── Street (Main St)      → Class selector (target .highlight)
└── House Number (123)    → ID selector (target #intro)

The more specific the address, the fewer recipients.

Anatomy of a CSS Rule

Before diving into selectors, understand the CSS structure:

selector {
  property: value;
}

Example:

p {
  color: blue;
}

Parts:

p           → Selector (WHAT to style)
{...}       → Declaration block
color       → Property (WHICH aspect to style)
blue        → Value (HOW to style it)

Visual breakdown:

┌─────────────────────────────────────────────────────────────┐
│  CSS RULE ANATOMY                                           │
└─────────────────────────────────────────────────────────────┘

    ┌─ Selector: Targets elements
    │
    p {
      color: blue;
      │     │
      │     └─ Value: What to apply
      │
      └─ Property: What to change
    }

1. Element Selector (Type Selector)

The element selector targets all elements of a specific type.

Syntax

elementname {
  /* styles */
}

Examples

/* Target ALL paragraphs */
p {
  color: blue;
}

/* Target ALL headings level 1 */
h1 {
  font-size: 32px;
}

/* Target ALL divs */
div {
  background-color: lightgray;
}

/* Target ALL links */
a {
  text-decoration: none;
}

HTML + CSS Example

HTML:

<h1>Welcome</h1>
<p>First paragraph</p>
<p>Second paragraph</p>
<p>Third paragraph</p>

CSS:

p {
  color: blue;
  font-size: 16px;
}

Result:

┌─────────────────────────────────────────────────────────────┐
│  RENDERED OUTPUT                                            │
└─────────────────────────────────────────────────────────────┘

Welcome                          ← h1 (not affected)

First paragraph                  ← p (blue, 16px)
Second paragraph                 ← p (blue, 16px)
Third paragraph                  ← p (blue, 16px)

When to Use

✓ Style all elements of one type consistently
✓ Set base styles (all paragraphs, all headings)
✓ Reset default browser styles

Example use cases:
├── Make all links blue
├── Give all paragraphs the same font size
└── Remove underlines from all links

Visual: How Element Selectors Work

┌─────────────────────────────────────────────────────────────┐
│  ELEMENT SELECTOR TARGETING                                 │
└─────────────────────────────────────────────────────────────┘

HTML:
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<div>Box</div>
<p>Paragraph 3</p>

CSS:
p { color: red; }

Targets:
<h1>Title</h1>          ✗ (not a <p>)
<p>Paragraph 1</p>      ✓ (turns red)
<p>Paragraph 2</p>      ✓ (turns red)
<div>Box</div>          ✗ (not a <p>)
<p>Paragraph 3</p>      ✓ (turns red)

2. Class Selector

The class selector targets elements with a specific class attribute.

Syntax

.classname {
  /* styles */
}

Note the dot (.) prefix!

HTML Setup

<p>Normal paragraph</p>
<p class="highlight">Highlighted paragraph</p>
<p class="highlight">Another highlighted paragraph</p>
<div class="highlight">Highlighted div</div>

CSS

.highlight {
  background-color: yellow;
  font-weight: bold;
}

Result

┌─────────────────────────────────────────────────────────────┐
│  RENDERED OUTPUT                                            │
└─────────────────────────────────────────────────────────────┘

Normal paragraph                  ← Not highlighted

Highlighted paragraph             ← Yellow background, bold
Another highlighted paragraph     ← Yellow background, bold
Highlighted div                   ← Yellow background, bold

Key Points

✓ Classes are REUSABLE (multiple elements can share one class)
✓ Elements can have MULTIPLE classes
✓ Classes work across different element types
✓ Use meaningful class names (highlight, button, card, etc.)

Multiple Classes

HTML:

<p class="highlight important">Very important text</p>

CSS:

.highlight {
  background-color: yellow;
}

.important {
  color: red;
  font-weight: bold;
}

Result:

Very important text
↑ Yellow background (from .highlight)
↑ Red, bold text (from .important)

Visual: How Class Selectors Work

┌─────────────────────────────────────────────────────────────┐
│  CLASS SELECTOR TARGETING                                   │
└─────────────────────────────────────────────────────────────┘

HTML:
<p>Normal</p>
<p class="special">Special paragraph</p>
<div>Normal div</div>
<div class="special">Special div</div>

CSS:
.special { color: green; }

Targets:
<p>Normal</p>                     ✗ (no class)
<p class="special">...</p>        ✓ (has .special class)
<div>Normal div</div>             ✗ (no class)
<div class="special">...</div>    ✓ (has .special class)

Naming Conventions

✓ GOOD class names:
├── .button
├── .card
├── .highlight
├── .nav-menu
└── .user-profile

✗ BAD class names:
├── .red (describes appearance, not purpose)
├── .big (too vague)
├── .style1 (meaningless)
├── .asdf (no meaning)
└── .DIV (uppercase, confusing)

3. ID Selector

The ID selector targets ONE unique element with a specific ID.

Syntax

#idname {
  /* styles */
}

Note the hash (#) prefix!

HTML Setup

<h1 id="main-title">My Website</h1>
<p id="intro">Introduction paragraph</p>
<p>Regular paragraph</p>
<p>Another regular paragraph</p>

CSS

#main-title {
  color: darkblue;
  font-size: 48px;
}

#intro {
  font-style: italic;
  color: gray;
}

Result

┌─────────────────────────────────────────────────────────────┐
│  RENDERED OUTPUT                                            │
└─────────────────────────────────────────────────────────────┘

My Website                        ← Dark blue, 48px
                                     (from #main-title)

Introduction paragraph            ← Italic, gray
                                     (from #intro)

Regular paragraph                 ← No special styling

Another regular paragraph         ← No special styling

Key Points

✓ IDs must be UNIQUE (one per page)
✓ IDs are more SPECIFIC than classes
✓ Use for truly unique elements (header, main-content, footer)
✗ Don't reuse the same ID multiple times on one page

Class vs ID: When to Use What

┌─────────────────────────────────────────────────────────────┐
│  CLASS vs ID DECISION GUIDE                                 │
└─────────────────────────────────────────────────────────────┘

Use CLASS when:
├── Style applies to MULTIPLE elements
├── Element might repeat (buttons, cards, list items)
└── General styling patterns

Example:
<button class="btn">Click</button>
<button class="btn">Submit</button>
<button class="btn">Cancel</button>


Use ID when:
├── Element is UNIQUE on the page
├── Only ONE instance exists
└── Need to target with JavaScript or anchors

Example:
<header id="main-header">...</header>
<main id="content">...</main>
<footer id="main-footer">...</footer>

Visual: How ID Selectors Work

┌─────────────────────────────────────────────────────────────┐
│  ID SELECTOR TARGETING                                      │
└─────────────────────────────────────────────────────────────┘

HTML:
<h1 id="hero-title">Welcome</h1>
<p>Paragraph 1</p>
<p id="intro">Introduction</p>
<p>Paragraph 2</p>

CSS:
#intro { color: purple; }

Targets:
<h1 id="hero-title">Welcome</h1>    ✗ (different ID)
<p>Paragraph 1</p>                  ✗ (no ID)
<p id="intro">Introduction</p>      ✓ (matches #intro)
<p>Paragraph 2</p>                  ✗ (no ID)

4. Group Selectors

Group selectors let you apply the same styles to multiple selectors at once.

Syntax

selector1, selector2, selector3 {
  /* styles */
}

Note the commas (,) separating selectors!

Example

Without grouping (repetitive):

h1 {
  color: navy;
  font-family: Arial;
}

h2 {
  color: navy;
  font-family: Arial;
}

h3 {
  color: navy;
  font-family: Arial;
}

With grouping (efficient):

h1, h2, h3 {
  color: navy;
  font-family: Arial;
}

Both produce the same result, but grouping is cleaner!

Complex Grouping

You can group any combination of selectors:

/* Group element, class, and ID selectors */
h1, .special, #intro {
  text-align: center;
}

HTML:

<h1>Title</h1>
<p class="special">Special paragraph</p>
<div id="intro">Introduction</div>
<p>Regular paragraph</p>

Result:

All three elements (h1, .special, #intro) are centered
Regular paragraph remains left-aligned

Visual: How Group Selectors Work

┌─────────────────────────────────────────────────────────────┐
│  GROUP SELECTOR TARGETING                                   │
└─────────────────────────────────────────────────────────────┘

CSS:
h1, p, .box { color: red; }

Equivalent to:
h1 { color: red; }
p { color: red; }
.box { color: red; }

HTML:
<h1>Title</h1>          ✓ (red)
<p>Text</p>            ✓ (red)
<div class="box">...</div>  ✓ (red)
<span>Text</span>      ✗ (not targeted)

When to Use

✓ Multiple elements need identical styles
✓ Reduce CSS repetition
✓ Keep code DRY (Don't Repeat Yourself)

Example use cases:
├── All headings same color
├── Multiple buttons same background
└── Several sections same padding

5. Descendant Selectors (Combinator)

Descendant selectors target elements that are INSIDE other elements.

Syntax

ancestor descendant {
  /* styles */
}

Note the space between selectors!

Example

HTML:

<div class="container">
  <p>Paragraph inside container</p>
  <p>Another paragraph inside container</p>
</div>

<p>Paragraph outside container</p>

CSS:

.container p {
  color: blue;
}

Result:

┌─────────────────────────────────────────────────────────────┐
│  RENDERED OUTPUT                                            │
└─────────────────────────────────────────────────────────────┘

Paragraph inside container        ← Blue (inside .container)
Another paragraph inside container ← Blue (inside .container)

Paragraph outside container       ← Normal (NOT inside .container)

Deeper Nesting

Descendant selectors work at ANY depth:

HTML:

<div class="box">
  <article>
    <section>
      <p>Deeply nested paragraph</p>
    </section>
  </article>
</div>

CSS:

.box p {
  color: green;
}

Result:

The <p> is styled green even though it's 3 levels deep!

Multiple Levels

/* Target links inside list items inside nav */
nav li a {
  text-decoration: none;
}

HTML:

<nav>
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
  </ul>
</nav>

<a href="#">Link outside nav</a>

Result:

Links inside <nav>: No underline
Link outside <nav>: Normal underline

Visual: How Descendant Selectors Work

┌─────────────────────────────────────────────────────────────┐
│  DESCENDANT SELECTOR TARGETING                              │
└─────────────────────────────────────────────────────────────┘

CSS:
div p { color: orange; }

HTML:
<div>
  <p>Paragraph 1</p>      ✓ (p inside div)
  <section>
    <p>Paragraph 2</p>    ✓ (p inside div, any depth)
  </section>
</div>

<p>Paragraph 3</p>        ✗ (p NOT inside div)

Structure:
div
 ├── p ✓
 └── section
      └── p ✓

p ✗ (outside div)

When to Use

✓ Style elements only in specific contexts
✓ Override general styles in specific sections
✓ Create scoped styling

Example use cases:
├── Links in navigation vs links in content
├── Paragraphs in sidebar vs main content
└── Images in header vs images in footer

Selector Priority (Specificity) – High Level

When multiple CSS rules target the same element, specificity determines which rule wins.

The Hierarchy (Simplified)

┌─────────────────────────────────────────────────────────────┐
│  SELECTOR PRIORITY (LOWEST TO HIGHEST)                      │
└─────────────────────────────────────────────────────────────┘

1. Element selector            (weakest)
   p { color: blue; }

2. Class selector
   .highlight { color: green; }

3. ID selector                 (strongest)
   #intro { color: red; }

Example: Specificity in Action

HTML:

<p id="intro" class="highlight">What color am I?</p>

CSS:

p {
  color: blue;          /* Element selector */
}

.highlight {
  color: green;         /* Class selector */
}

#intro {
  color: red;           /* ID selector */
}

Result:

Text is RED

Why? ID selector (#intro) beats class (.highlight) beats element (p)

Visual: Specificity Hierarchy

┌─────────────────────────────────────────────────────────────┐
│  SPECIFICITY WEIGHT                                         │
└─────────────────────────────────────────────────────────────┘

ID Selector (#)
██████████████████████  (Most specific - weight: 100)

Class Selector (.)
██████████  (Medium specific - weight: 10)

Element Selector
███  (Least specific - weight: 1)

When rules conflict, highest weight wins

Combining Selectors Increases Specificity

/* Low specificity */
p {
  color: blue;
}

/* Medium specificity */
.container p {
  color: green;
}

/* Higher specificity */
.container .highlight {
  color: orange;
}

/* Highest specificity */
#intro {
  color: red;
}

Rule of thumb:

More specific selector = Higher priority

Important Note for Beginners

Don't worry too much about specificity yet!

For now, remember:
├── IDs are strongest
├── Classes are medium
└── Elements are weakest

As you learn more CSS, specificity will become clearer.

Complete Example: Putting It All Together

Let's build a simple card component using different selectors:

HTML:

<div class="card">
  <h2 id="card-title">Product Name</h2>
  <p class="description">This is a product description.</p>
  <p class="price">$29.99</p>
  <button class="btn">Buy Now</button>
</div>

<p>Regular paragraph outside card</p>
<button>Regular button</button>

CSS:

/* Element selector - all cards get padding */
.card {
  padding: 20px;
  border: 1px solid gray;
  background-color: white;
}

/* ID selector - unique title */
#card-title {
  color: darkblue;
  font-size: 24px;
}

/* Class selector - description styling */
.description {
  color: #666;
  font-size: 14px;
}

/* Class selector - price styling */
.price {
  color: green;
  font-weight: bold;
  font-size: 20px;
}

/* Class selector - button styling */
.btn {
  background-color: blue;
  color: white;
  padding: 10px 20px;
  border: none;
}

/* Descendant selector - only paragraphs in card */
.card p {
  margin: 10px 0;
}

/* Group selector - all headings */
h1, h2, h3 {
  font-family: Arial, sans-serif;
}

Result:

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  Product Name          ← #card-title (blue, 24px)          │
│                                                             │
│  This is a product     ← .description (gray, 14px)          │
│  description.                                               │
│                                                             │
│  $29.99                ← .price (green, bold, 20px)         │
│                                                             │
│  ┌──────────┐                                               │
│  │ Buy Now  │          ← .btn (blue bg, white text)        │
│  └──────────┘                                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Regular paragraph outside card  ← No .card p styling

┌────────────┐
│ Button     │  ← No .btn styling
└────────────┘

Selector Quick Reference

┌─────────────────────────────────────────────────────────────┐
│  CSS SELECTOR CHEAT SHEET                                   │
└─────────────────────────────────────────────────────────────┘

BASIC SELECTORS
───────────────────────────────────────────────────────────────

Element Selector
p { }               All <p> elements

Class Selector
.classname { }      All elements with class="classname"

ID Selector
#idname { }         Element with id="idname"

Group Selector
h1, h2, p { }       All h1, h2, and p elements

Descendant Selector
div p { }           All <p> inside <div> (any depth)


SPECIFICITY (Simple)
───────────────────────────────────────────────────────────────

Element < Class < ID

p { }               Weakest
.box { }            Medium
#header { }         Strongest

Common Mistakes and How to Avoid Them

1. Forgetting the Dot for Classes

WRONG:
highlight {
  color: yellow;
}

✓ CORRECT:
.highlight {
  color: yellow;
}

2. Forgetting the Hash for IDs

WRONG:
intro {
  font-size: 18px;
}

✓ CORRECT:
#intro {
  font-size: 18px;
}

3. Using IDs Multiple Times

❌ WRONG:
<p id="special">Text 1</p>
<p id="special">Text 2</p>

✓ CORRECT:
<p class="special">Text 1</p>
<p class="special">Text 2</p>

4. Missing Space in Descendant Selector

WRONG (this is a different selector!):
div.box {
  /* Targets <div class="box">, not descendants */
}

✓ CORRECT (descendant selector):
div .box {
  /* Targets .box inside <div> */
}

5. Overusing IDs

AVOID:
#button1 { }
#button2 { }
#button3 { }

✓ BETTER:
.button { }  /* Reusable class */

Practice Exercises

Try styling these HTML structures:

Exercise 1: Basic Selectors

HTML:

<h1>Main Title</h1>
<p class="intro">Introduction paragraph</p>
<p>Regular paragraph</p>
<p id="conclusion">Conclusion paragraph</p>

Task:

1. Make <h1> dark blue
2. Make .intro italic
3. Make #conclusion bold and green
4. Make all <p> elements have 16px font size

Exercise 2: Descendant Selectors

HTML:

<div class="box">
  <h2>Box Title</h2>
  <p>Text inside box</p>
</div>

<h2>Outside Title</h2>
<p>Text outside box</p>

Task:

1. Make paragraphs inside .box gray
2. Make headings inside .box blue
3. Leave outside elements unstyled

Exercise 3: Group Selectors

HTML:

<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<p>Paragraph</p>

Task:

1. Make all headings (h1, h2, h3) the same font family
2. Make only h1 and h2 navy blue
3. Make p a different color

Summary: The Foundation of CSS

CSS selectors are the targeting system that makes styling possible.

┌─────────────────────────────────────────────────────────────┐
│  WHAT YOU LEARNED                                           │
└─────────────────────────────────────────────────────────────┘

Element Selector
p { }                     Target all elements of a type

Class Selector
.classname { }            Target elements by class (reusable)

ID Selector
#idname { }               Target unique element by ID

Group Selector
h1, h2, p { }             Target multiple selectors at once

Descendant Selector
div p { }                 Target nested elements

Specificity
ID > Class > Element      Priority when rules conflict

Key Takeaways:

✓ Selectors tell CSS WHICH elements to style
✓ Element selectors target ALL of one type
✓ Classes are REUSABLE, IDs are UNIQUE
✓ Descendant selectors provide CONTEXT
✓ More specific selectors WIN conflicts

Master these basics before moving to advanced selectors (pseudo-classes, attribute selectors, etc.).

Selectors are the first step. Properties and values come next. But without selectors, you can't style anything at all! 🎯

More from this blog

ArmanRuhit Blogs

14 posts