Skip to main content

Command Palette

Search for a command to run...

CSS Selectors 101: Targeting Elements with Precision

Learn how to target HTML elements with CSS selectors — element, class, ID, group, and descendant selectors explained with examples.

Updated
11 min read
CSS Selectors 101: Targeting Elements with Precision
V

BCA student and developer who loves learning in public. I build web and mobile projects, explore databases and backend systems, and document my journey through blogs. Currently focused on writing clean code and growing one commit at a time.

CSS Selectors 101: Targeting Elements with Precision

You've written your HTML. Now you want to make it look good with CSS. But how do you tell CSS which elements to style? That's where selectors come in.

CSS selectors are the foundation of styling. They let you point at specific elements and say, "Apply these styles here." Master selectors, and you master CSS targeting.

Introduction

Imagine you're in a crowded room and need to get someone's attention. You might:

  • Shout "Everyone!" → Everyone responds

  • Shout "All teachers!" → Only teachers respond

  • Shout "John Smith!" → Only John responds

CSS selectors work the same way — they're how you address elements on your page.

In this guide, we'll cover the essential selectors every beginner needs to know.

Prerequisites

  • Basic understanding of HTML tags and elements

  • A text editor and browser for experimenting


What Are CSS Selectors?

A CSS selector is a pattern that tells the browser which elements to style.

The Basic CSS Rule Structure

selector {
    property: value;
}
┌─────────────────────────────────────────────────────────────────┐
│                    Anatomy of a CSS Rule                         │
└─────────────────────────────────────────────────────────────────┘

         SELECTOR           DECLARATION BLOCK
             │                     │
             ▼              ┌──────┴──────┐
             │              │             │
             p      {    color: blue;     }
             │       │      │       │     │
             │       │      │       │     └─ Closing brace
             │       │      │       └─ Value
             │       │      └─ Property
             │       └─ Opening brace
             └─ Selector (targets all <p> elements)

The selector is the "address" — it tells CSS where to deliver the styles.

Real-World Analogy: Addressing People

Think of selectors like addressing people in different ways:

┌─────────────────────────────────────────────────────────────────┐
│               Selectors as Ways to Address People                │
└─────────────────────────────────────────────────────────────────┘

    How You Address              CSS Equivalent
    ────────────────             ──────────────

    "Hey, everyone!"      →      * (universal selector)

    "All students!"       →      element selector (p, div, h1)

    "All seniors!"        →      .class selector (.senior)

    "John Smith!"         →      #id selector (#john-smith)

    "Students in Room 5"  →      descendant selector (div p)

Let's explore each type of selector.


Element Selector

The element selector (also called type selector) targets all elements of a specific HTML tag.

Syntax

tagname {
    /* styles */
}

Example

<h1>Welcome</h1>
<p>First paragraph.</p>
<p>Second paragraph.</p>
<p>Third paragraph.</p>
p {
    color: blue;
    font-size: 16px;
}

Result: ALL <p> elements turn blue with 16px font.

┌─────────────────────────────────────────────────────────────────┐
│                  Element Selector in Action                      │
└─────────────────────────────────────────────────────────────────┘

    HTML                              Result
    ────                              ──────

    <h1>Welcome</h1>                  Welcome (unchanged)

    <p>First paragraph.</p>    →      First paragraph.  (BLUE)
    <p>Second paragraph.</p>   →      Second paragraph. (BLUE)
    <p>Third paragraph.</p>    →      Third paragraph.  (BLUE)

                                         ▲
    CSS: p { color: blue; }              │
              │                          │
              └──────── targets all ─────┘

When to Use

  • When you want consistent styling for ALL elements of a type

  • For base styles (all paragraphs, all headings, all links)

Common Element Selectors

/* All headings */
h1 {
    font-size: 32px;
}
h2 {
    font-size: 24px;
}

/* All paragraphs */
p {
    line-height: 1.6;
}

/* All links */
a {
    color: blue;
}

/* All images */
img {
    max-width: 100%;
}

💡 Tip: Element selectors are great for setting base styles, but they affect EVERY element of that type. For more control, use classes.


Class Selector

The class selector targets elements that have a specific class attribute. Classes are reusable — multiple elements can share the same class.

Syntax

.classname {
    /* styles */
}

Note the dot (.) before the class name!

Example

<p>Regular paragraph.</p>
<p class="highlight">Highlighted paragraph.</p>
<p class="highlight">Another highlighted one.</p>
<p>Another regular paragraph.</p>
.highlight {
    background-color: yellow;
    font-weight: bold;
}

Result: Only paragraphs with class="highlight" get the yellow background.

┌─────────────────────────────────────────────────────────────────┐
│                   Class Selector in Action                       │
└─────────────────────────────────────────────────────────────────┘

    HTML                                    Result
    ────                                    ──────

    <p>Regular paragraph.</p>               Regular paragraph.
                                            (normal)

    <p class="highlight">Highlighted</p>    ████████████████████
                                            █  Highlighted      █ YELLOW!
                                            ████████████████████

    <p class="highlight">Another</p>        ████████████████████
                                            █  Another          █ YELLOW!
                                            ████████████████████

    <p>Another regular.</p>                 Another regular.
                                            (normal)

    CSS: .highlight { background: yellow; }
          │
          └─ The dot means "class"

Multiple Classes

An element can have multiple classes:

<p class="highlight large">Big and highlighted!</p>
.highlight {
    background-color: yellow;
}

.large {
    font-size: 24px;
}

The paragraph gets BOTH styles applied.

When to Use

  • When multiple elements need the same style

  • When you want reusable styling

  • Most common selector in real-world CSS

ℹ️ Note: Class names should be descriptive: .error-message, .nav-link, .card-title — not .red or .big.


ID Selector

The ID selector targets a single, unique element with a specific id attribute. IDs should be unique — only one element per page should have a given ID.

Syntax

#idname {
    /* styles */
}

Note the hash (#) before the ID name!

Example

<header id="main-header">
    <h1>My Website</h1>
</header>

<nav id="main-nav">
    <a href="/">Home</a>
    <a href="/about">About</a>
</nav>
#main-header {
    background-color: navy;
    color: white;
    padding: 20px;
}

#main-nav {
    background-color: lightgray;
}

Result: The header gets navy background, the nav gets light gray — each targeted uniquely.

┌─────────────────────────────────────────────────────────────────┐
│                    ID Selector in Action                         │
└─────────────────────────────────────────────────────────────────┘

    HTML                                    CSS Target
    ────                                    ──────────

    <header id="main-header">       ←───    #main-header { ... }
      <h1>My Website</h1>                   (only this header)
    </header>

    <nav id="main-nav">             ←───    #main-nav { ... }
      <a>Home</a>                           (only this nav)
      <a>About</a>
    </nav>


    ID = Unique identifier (like a Social Security Number)
         Only ONE element should have each ID

Class vs ID: Key Differences

┌─────────────────────────────────────────────────────────────────┐
│                     Class vs ID                                  │
└─────────────────────────────────────────────────────────────────┘

         CLASS (.)                         ID (#)
         ─────────                         ──────

    • Reusable                        • Unique (one per page)

    • Multiple elements               • Single element only
      can share it

    • Lower specificity               • Higher specificity

    • Use for styling                 • Use for unique elements
                                        (or JavaScript targets)

    Example:                          Example:
    .button { ... }                   #main-header { ... }
    .card { ... }                     #submit-form { ... }

    Many buttons, many cards          Only one header, one form

When to Use

  • For truly unique elements (main header, main footer)

  • When JavaScript needs to target a specific element

  • Use sparingly — classes are usually more flexible

⚠️ Warning: Avoid using IDs for styling when classes would work. IDs have high specificity, which can make your CSS harder to override later.


Group Selectors

Sometimes you want to apply the same styles to multiple selectors. Group selectors let you combine them with commas.

Syntax

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

Example: Without Grouping

h1 {
    font-family: Arial, sans-serif;
    color: navy;
}

h2 {
    font-family: Arial, sans-serif;
    color: navy;
}

h3 {
    font-family: Arial, sans-serif;
    color: navy;
}

Repetitive! Let's group them.

Example: With Grouping

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

Same result, much cleaner!

┌─────────────────────────────────────────────────────────────────┐
│                   Group Selector in Action                       │
└─────────────────────────────────────────────────────────────────┘

    CSS Rule                              Elements Targeted
    ────────                              ─────────────────

    h1, h2, h3 {                          <h1>...</h1>  ←─┐
      font-family: Arial;         →       <h2>...</h2>  ←─┼─ All get
      color: navy;                        <h3>...</h3>  ←─┘  the styles
    }


    .btn, .link, .nav-item {              <a class="btn">      ←─┐
      cursor: pointer;            →       <span class="link">  ←─┼─ All get
      text-decoration: none;              <li class="nav-item">←─┘  the styles
    }

Mixing Selector Types

You can group different types of selectors:

/* Mix element, class, and ID selectors */
h1,
.title,
#main-heading {
    font-weight: bold;
    margin-bottom: 10px;
}

💡 Tip: Use grouping to keep your CSS DRY (Don't Repeat Yourself). If multiple selectors share styles, group them!


Descendant Selectors

The descendant selector targets elements that are inside (descendants of) another element.

Syntax

ancestor descendant {
    /* styles */
}

Note: Just a space between selectors!

Example

<div class="card">
    <p>This paragraph is inside the card.</p>
</div>

<p>This paragraph is outside.</p>
.card p {
    color: blue;
}

Result: Only the paragraph INSIDE .card turns blue.

┌─────────────────────────────────────────────────────────────────┐
│                Descendant Selector in Action                     │
└─────────────────────────────────────────────────────────────────┘

    HTML Structure                        CSS Target: .card p
    ──────────────                        ───────────────────

    <div class="card">
      │
      └──► <p>Inside the card</p>    ←──  ✅ TARGETED (inside .card)
    </div>

    <p>Outside</p>                   ←──  ❌ NOT targeted (not in .card)


    .card p means: "paragraphs that are INSIDE elements with class card"

Multiple Levels

Descendant selectors work at any nesting level:

<article>
    <section>
        <p>Deeply nested paragraph.</p>
    </section>
</article>
article p {
    /* Targets the <p> even though it's inside <section> */
    color: green;
}

Practical Examples

/* Links inside navigation */
nav a {
    color: white;
    text-decoration: none;
}

/* List items inside unordered lists */
ul li {
    margin-bottom: 10px;
}

/* Paragraphs inside cards */
.card p {
    font-size: 14px;
    line-height: 1.5;
}

/* Bold text inside headers */
header strong {
    color: gold;
}

Combining with Other Selectors

/* Only paragraphs with class "intro" inside articles */
article p.intro {
    font-size: 18px;
    font-style: italic;
}

ℹ️ Note: Descendant selectors look for elements at ANY depth. For direct children only, use the child selector (>), but that's for another lesson!


Selector Priority (Specificity Basics)

What happens when multiple rules target the same element? CSS uses specificity to decide which rule wins.

The Basic Hierarchy

┌─────────────────────────────────────────────────────────────────┐
│                  Selector Priority (Specificity)                 │
└─────────────────────────────────────────────────────────────────┘

    HIGHEST PRIORITY
         ▲
         │
    ┌────┴────┐
    │ Inline  │   style="color: red;"     (most powerful)
    │ styles  │
    └────┬────┘
         │
    ┌────┴────┐
    │   ID    │   #header { }             (very specific)
    │selector │
    └────┬────┘
         │
    ┌────┴────┐
    │  Class  │   .button { }             (moderately specific)
    │selector │
    └────┬────┘
         │
    ┌────┴────┐
    │ Element │   p { }                   (least specific)
    │selector │
    └────┬────┘
         │
         ▼
    LOWEST PRIORITY

Example: Specificity in Action

<p id="special" class="highlight">Hello World</p>
p {
    color: black; /* Specificity: 0-0-1 */
}

.highlight {
    color: blue; /* Specificity: 0-1-0 */
}

#special {
    color: red; /* Specificity: 1-0-0 */
}

Result: The text is red because #special has the highest specificity.

How Specificity Scores Work

Think of it as a three-digit number:

Selector TypeScoreExample
ID1-0-0#header
Class0-1-0.button
Element0-0-1p

Compare like a number: 1-0-0 > 0-1-0 > 0-0-1

Combining Selectors

Selectors combine their specificity:

/* 0-0-1 (one element) */
p {
}

/* 0-1-1 (one class + one element) */
p.intro {
}

/* 0-2-0 (two classes) */
.card.featured {
}

/* 1-1-0 (one ID + one class) */
#main .highlight {
}

When Rules Tie

If two selectors have equal specificity, the last one wins (source order):

p {
    color: blue;
}

p {
    color: red; /* This wins — it comes last */
}

Practical Advice

┌─────────────────────────────────────────────────────────────────┐
│                  Specificity Best Practices                      │
└─────────────────────────────────────────────────────────────────┘

    ✅ DO:
    • Use classes for most styling (.btn, .card, .nav-link)
    • Keep specificity low and consistent
    • Use element selectors for base styles

    ❌ AVOID:
    • Overusing ID selectors (hard to override)
    • Using !important (last resort only)
    • Creating specificity wars

    Rule of thumb:
    Classes > IDs for styling
    Low specificity = Flexible CSS

💡 Tip: Don't memorize specificity numbers. Just remember: ID beats Class beats Element. When in doubt, use classes!


Choosing the Right Selector

Here's a quick guide for when to use each selector:

┌─────────────────────────────────────────────────────────────────┐
│                 When to Use Each Selector                        │
└─────────────────────────────────────────────────────────────────┘

    ┌─────────────────────────────────────────────────────────────┐
    │  ELEMENT SELECTOR (p, h1, div)                              │
    │  ─────────────────────────────                              │
    │  ✓ Base styles for all elements of a type                   │
    │  ✓ Reset/normalize styles                                   │
    │  Example: All paragraphs should have line-height: 1.6       │
    └─────────────────────────────────────────────────────────────┘
                              │
                              ▼
    ┌─────────────────────────────────────────────────────────────┐
    │  CLASS SELECTOR (.classname)                                │
    │  ───────────────────────────                                │
    │  ✓ Reusable styles across multiple elements                 │
    │  ✓ Component styling (buttons, cards, forms)                │
    │  ✓ Most common — use this as your default!                  │
    │  Example: All elements with .btn should look like buttons   │
    └─────────────────────────────────────────────────────────────┘
                              │
                              ▼
    ┌─────────────────────────────────────────────────────────────┐
    │  ID SELECTOR (#idname)                                      │
    │  ─────────────────────                                      │
    │  ✓ Unique elements (only one on the page)                   │
    │  ✓ JavaScript targeting                                     │
    │  ✓ Use sparingly for CSS                                    │
    │  Example: #main-header for the one main header              │
    └─────────────────────────────────────────────────────────────┘
                              │
                              ▼
    ┌─────────────────────────────────────────────────────────────┐
    │  DESCENDANT SELECTOR (parent child)                         │
    │  ──────────────────────────────────                         │
    │  ✓ Context-specific styling                                 │
    │  ✓ Targeting elements only in certain containers            │
    │  Example: .nav a for links only inside navigation           │
    └─────────────────────────────────────────────────────────────┘

Summary Table

SelectorSyntaxUse ForReusable?
ElementpBase stylesN/A (targets all)
Class.nameComponent styles✅ Yes
ID#nameUnique elements❌ No (should be unique)
Groupa, b, cShared styles✅ Yes
Descendanta bNested elements✅ Yes

Best Practices

  • Start with element selectors for base styles

  • Use classes for almost everything — they're flexible and reusable

  • Reserve IDs for unique elements or JavaScript hooks

  • Group selectors to avoid repetition

  • Keep specificity low — easier to maintain and override

Common Mistakes to Avoid

  1. Forgetting the dot or hash

     /* Wrong */
     highlight {
         color: yellow;
     }
    
     /* Right */
     .highlight {
         color: yellow;
     }
    
  2. Using IDs for everything

     /* Avoid — IDs are too specific */
     #btn-1 {
     }
     #btn-2 {
     }
     #btn-3 {
     }
    
     /* Better — use a class */
     .btn {
     }
    
  3. Overly specific selectors

     /* Avoid — too specific, hard to maintain */
     div.container article section p.intro {
     }
    
     /* Better — simpler, more reusable */
     .intro {
     }
    
  4. Relying on !important

     /* Avoid — sign of specificity problems */
     p {
         color: red !important;
     }
    
     /* Better — fix the specificity issue */
    

Conclusion

CSS selectors are the foundation of styling. They're how you tell CSS which elements to target:

  • Element selectors (p, h1) target all elements of a type

  • Class selectors (.classname) target elements with a specific class — use these most!

  • ID selectors (#idname) target unique elements

  • Group selectors (a, b, c) apply the same styles to multiple selectors

  • Descendant selectors (parent child) target elements inside other elements

  • Specificity determines which rule wins when there's a conflict

Master these basics, and you'll have the control you need to style any webpage.

Next Steps / Further Reading

  • Practice combining selectors in real projects

  • Learn about pseudo-classes (:hover, :first-child)

  • Explore the child selector (>) and sibling selectors (+, ~)

  • Dive deeper into CSS specificity and the cascade


If you found this helpful, consider following for more CSS and web development fundamentals.