Skip to main content

Command Palette

Search for a command to run...

CSS Selectors Explained: How to Choose the Right Elements

Updated
10 min read

When you write CSS, you're constantly answering one question: "Which elements do I want to style?"

Without a way to point at specific elements in your HTML, you couldn't change colors, fonts, or layout. CSS selectors are exactly that: they're the way you choose which elements get which styles.

In this article w, we'll cover:

Why are CSS selectors needed

Element selector – style by tag name

Class selector – style by class name

ID selector – style by ID

Group selectors – style multiple things at once

Descendant selectors – style elements inside other elements

Basic selector priority – why some rules win over others

We'll use a simple "addressing people" analogy, start from the basics, and show before/after examples so you can see selectors in action.

Why CSS Selectors Are Needed

The basic problem

Your HTML page has many elements: headings, paragraphs, buttons, links, lists, and more. Your CSS needs to say:

"Make all paragraphs blue."

"Make this button red."

"Make everything inside the sidebar smaller."

If you had no way to target specific elements, you'd have to style everything the same – or not style at all.

Selectors are the mechanism that lets you say: "Apply these styles to *these** elements."*

Real-world analogy: Addressing people

Imagine a room full of people:

"Everyone named John" → You're selecting by name (like an element selector).

"Everyone wearing a red shirt" → You're selecting by what they're wearing (like a class selector).

"The person with badge #42" → You're selecting by unique ID (like an ID selector).

"Everyone named John who is inside the left corner" → You're selecting by name + location (like a descendant selector).

CSS selectors work the same way: they're different ways of addressing elements so the browser knows who gets which style.

Selectors are the foundation of CSS

Every CSS rule has two parts:

1. Selectorwhich elements

2. Declaration blockwhat styles to apply

selector {
  property: value;
}

If you don't understand selectors, you can't control where your styles go. So think of selectors as the foundation of CSS: everything else (colors, layout, animations) builds on top of "which element?"

Element Selector – Style by Tag Name

What it does

The element selector (also called type selector) selects every element that matches a given HTML tag name.

You write it as the tag name itself, with no extra symbol (no . or #).

Syntax

elementname {
  /* styles */
}

Examples

Select all paragraphs:

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

Select all headings of level 1:

h1 {
  color: darkgreen;
  font-size: 2rem;
}

Select all links:

a {
  color: purple;
  text-decoration: underline;
}

Before / After

Before (no CSS):

All elements use the browser’s default styles (black text, default font, etc.).

After (with element selectors):

p { color: blue; }
h1 { color: darkgreen; }
a { color: purple; }

Now every <p> is blue, every <h1> is dark green, and every <a> is purple. You didn’t have to add anything to the HTML – the tag name is enough.

When to use it

Use the element selector when you want the same style for every instance of that tag (e.g. all paragraphs, all level‑2 headings). It’s broad and simple.

Class Selector – Style by Class Name

What it does

The class selector selects every element that has a specific class in its class attribute.

In HTML, you can give an element one or more classes: class="button primary". In CSS, you target a class with a dot (`.`) before the class name.

Syntax

classname {
  /* styles */
}

The dot (`.`) means "class." No dot = element name; dot = class name.

HTML + CSS example

HTML:

<p class="highlight">This paragraph is important.</p>
<p>This one is normal.</p>
<p class="highlight">This one is important too.</p>

CSS:

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

Only the paragraphs with class="highlight" get the yellow background and bold text. The one in the middle stays normal.

Before / After

Before:

Three paragraphs, all look the same (default styling).

After:

The two with class="highlight" are yellow and bold; the one without stays default. So the class is what you use when you want to style some elements of the same type (or different types) the same way.

Multiple classes

An element can have multiple classes: class="button primary". You can target:

- Exactly that combination (e.g., elements that have both button and primary):

 .button.primary { }

- Any element that has that class (among others):

 .primary { }

So classes are flexible: one element can share styles with many others by sharing a class name.

When to use it

Use the class selector when you want to style a group of elements the same way, whether they’re the same tag or not (e.g., "all buttons that look primary", "all highlighted boxes"). Reuse is the key idea: many elements can share one class.

ID Selector – Style by ID

What it does

The **ID selector** selects the **one element** that has a **specific id** in its id attribute.

In HTML, id is meant to be **unique** on the page (only one element per ID). In CSS, you target an ID with a **hash (*`#`)\* before the ID value.

Syntax

#idvalue {
  /* styles */
}

The hash (`#`) means "ID."

HTML + CSS example

HTML:

<header id="main-header">Welcome to my site</header>
<section id="hero">...</section>
<footer id="main-footer">© 2024</footer>

CSS:

#main-header {
  background-color: navy;
  color: white;
  padding: 1rem;
}

#main-footer {
  background-color: #333;
  color: #ccc;
  padding: 1rem;
}

Only the element with id="main-header" gets the navy header style, and only the one with id="main-footer" Gets the footer style.

Before / After

Before:

Header and footer look like normal blocks (default styling).

After:

The header has a navy background and white text; the footer has a dark background and light text. So the **ID** is what you use when you want to style **one specific** element on the page.

Class vs ID (high level)

| | Class | ID |

|---|--------|-----|

| **Symbol** | . (dot) | # (hash) |

| **In HTML** | class="name" | id="name" |

| **Uniqueness** | Many elements can share a class | One element per ID (by convention) |

| **Use when** | You want to style **a group** the same way | You want to style **one specific** element |

Rule of thumb:

Use **classes** for "this kind of thing" (buttons, cards, highlights).  
Use **IDs** for "this one thing" (main header, main content, contact form).
Class (.highlight)  →  Many elements can have it  →  "Everyone with a red shirt"
ID (#main-header)   →  Only one element has it    →  "The person with badge #42"

Group Selectors – Style Multiple Things at Once

What it does

Sometimes you want the same styles for several different selectors (e.g. all headings, or both h1 and p). Instead of repeating the same rule multiple times, you group the selectors with commas.

Syntax

selector1,
selector2,
selector3 {
  /* same styles for all */
}

A comma means "and" – "apply this block to selector1 and selector2 and selector3."

Example

Without grouping (repetition):

h1 {
  font-family: "Georgia", serif;
  color: #333;

}

h2 {
  font-family: "Georgia", serif;
  color: #333;
}

h3 {
  font-family: "Georgia", serif;
  color: #333;
}

With grouping (one rule):

h1,
h2,
h3 {
  font-family: "Georgia", serif;
  color: #333;
}

Same result, less code, easier to maintain.

Mixing selector types

You can group any mix of selectors:

h1,
.intro,
#main-title {
  font-size: 2rem;
  color: navy;
}

So group selectors are just a way to say: "these elements (whether by tag, class, or ID) all get this same set of styles."

Descendant Selectors – Style Elements Inside Other Elements

What it does

A descendant selector targets an element only when it is inside another element (anywhere nested: child, grandchild, etc.). You write two (or more) selectors separated by a space.

Syntax

ancestor descendant {
  /* styles */
}

The space means "inside" – "select descendant only when it is inside ancestor."

Example

HTML:

<article>
  <h2>Title</h2>
  <p>First paragraph.</p>
  <p>Second paragraph.</p>
</article>

<p>This paragraph is outside the article.</p>

CSS:

article p {
  color: blue;
  line-height: 1.6;
}

Only the <p> elements inside <article> turn blue and get the extra line height. The <p> that is outside <article> stays default. So the location (inside which parent) matters.

Before / After

Before:

All paragraphs look the same.

After:

Only the paragraphs inside <article> are blue with larger line height; the one outside is unchanged. So descendant selectors are the way you say: "style this element only when it’s inside that other element."

Deeper nesting

You can chain more than two:

header nav ul li a {
  color: white;
}

This means: "select <a> only when it is inside <li> inside <ul> inside <nav> inside <header>." So you can be as specific as your HTML structure.

When to use it

Use descendant selectors when you want styles to apply only in a certain part of the page (e.g. "links in the sidebar", "paragraphs in the main content"). It keeps styles scoped to context without giving every element a class.

Basic Selector Priority (Very High Level)

What happens when two rules conflict?

Sometimes two (or more) CSS rules try to style the same property on the same element. For example:

p { color: blue; }
.highlight { color: red; }

If a <p> has class="highlight", Should it be blue or red? The browser needs a way to decide. That’s specificity and source order.

Rough order of "strength" (conceptual)

Think of it like this (from weaker to stronger):

1. Element selector – "every p" – weakest.

2. Class selector – "every .highlight" – stronger than the element.

3. ID selector – "the one #main-title" – stronger than class.

So in a conflict:

ID beats class

Class beats element

Example

HTML:

<p id="intro" class="highlight">Hello world.</p>

CSS:

p           { color: blue; }   /* element */

.highlight  { color: red; }    /* class  – wins over p */

#intro      { color: green; }  /* ID     – wins over .highlight */

Result: the paragraph is green, because the ID selector wins.

Source order when strength is equal

When two selectors have the same "strength" (e.g. two classes, or two elements), the last rule in the CSS file wins:

.highlight { color: red; }
.highlight { color: blue; }  /* this one wins */

So: specificity first (ID > class > element), then order if specificity is equal.

HTML element

    ↓

Does it match an ID selector?     → Yes → Apply ID styles (and override weaker ones)

    ↓ No

Does it match a class selector?   → Yes → Apply class styles (and override element)

    ↓ No

Does it match an element selector? → Yes → Apply element styles

You don’t need to memorize exact specificity numbers yet – just remember: ID > class > element, and later rule wins when strength is the same.

Example

HTML:

<header id="site-header">
  <h1>My Blog</h1>
  <p class="tagline">Thoughts and code.</p>
</header>

<main>
  <article>
    <h2>First Post</h2>
    <p>Content here.</p>
    <p class="highlight">Key point.</p>
  </article>
</main>

CSS:

/* Element: all paragraphs */
p {
  font-size: 1rem;
  color: #333;
}

/* Class: highlighted paragraphs (and any .highlight) */

.highlight {
  background-color: #ffc;
  padding: 0.25rem;
}

/* ID: the one header */

#site-header {
  background-color: #333;
  color: white;
  padding: 1rem;
}

/* Descendant: only paragraphs inside header */

#site-header p {
  font-size: 0.9rem;
  color: #ccc;

}

/* Group: all headings in main */

main h1,
main h2 {
  font-family: Georgia, serif;
  color: #222;
}

Happy styling!

Have questions about Emmet? Drop them in the comments below!

```