Type, class and ID selectors

Target elements by type, class and ID, group selectors, and learn why classes are the everyday tool.

  • Beginner
  • 6 min read
  • Updated 17 Oct 2026

What you will learn

  • Target elements with type selectors
  • Target elements with classes
  • Group selectors
  • Explain why classes are usually better than IDs for styling

A selector tells the browser which elements a rule applies to. Three simple selectors cover most everyday styling: type, class and ID. Choosing the right one now saves you from fighting your own CSS later.

Type selectors

A type selector (also called an element selector) matches every element of that type:

CSS
p {
    line-height: 1.6;
}

a {
    color: #0b5394;
}

Every <p> and every <a> on the page is affected. Type selectors are ideal for base styles: sensible defaults for plain HTML elements such as body text, headings, links and lists.

They are too broad for anything more specific. If you style button to be large and blue, every button gets that look, including the small one in your cookie banner.

Class selectors

A class selector starts with a dot and matches elements with that value in their class attribute:

HTML
<p class="intro">Welcome to the shop.</p>
<p>Regular paragraph.</p>
<button class="button">Add to basket</button>
CSS
.intro {
    font-size: 1.25rem;
}

.button {
    padding: 0.75rem 1.25rem;
    border-radius: 0.375rem;
    background-color: #0b5394;
    color: white;
}

Only the first paragraph becomes larger. Classes are opt-in: an element is styled only when you give it the class.

Several classes on one element

The class attribute takes a space-separated list. Each class is a separate hook:

HTML
<button class="button button-large">Buy now</button>
CSS
.button-large {
    font-size: 1.25rem;
}

This button gets the styles from both .button and .button-large. Combining small classes like this is how most component styling works.

You can also require an element to have two classes at once by writing them together with no space:

CSS
.button.button-large {
    font-weight: 700;
}

Naming classes

  • Describe what it is, not how it looks: .alert ages better than .red-box.
  • Use lowercase and hyphens: .product-card, .site-header.
  • Class names are case-sensitive. .Card does not match class="card".
  • Do not start with a digit. .2col is not a valid selector.

ID selectors

An ID selector starts with # and matches the element with that id:

HTML
<header id="site-header">...</header>
CSS
#site-header {
    background-color: #102a43;
}

An id must be unique on the page. That alone makes IDs a poor fit for styling: you cannot reuse the style on a second element.

Why classes are usually the right choice

There is a second, bigger problem. ID selectors are much "stronger" than class selectors. In the next lesson you will learn this is called specificity. For now, see the effect:

HTML
<header id="site-header" class="header-dark">...</header>
CSS
#site-header {
    background-color: #102a43;
}

.header-dark {
    background-color: black; /* loses, even though it comes later */
}

The ID rule wins no matter where it appears. To override it you need another ID or something even stronger, and the stylesheet escalates into a battle.

Keep IDs for what they do well in HTML: link targets (href="#pricing"), connecting <label for="email"> to an input, and JavaScript hooks. Use classes for styling.

The universal selector

* matches every element. It is mostly used in resets:

CSS
* {
    margin: 0;
}

Use it sparingly. Applying heavy styles to every element makes everything harder to override.

Grouping selectors

When several selectors share the same declarations, separate them with commas:

CSS
h1,
h2,
h3 {
    font-family: Georgia, serif;
    line-height: 1.2;
}

.button,
.link-button {
    font-weight: 600;
}

This is exactly the same as writing three separate rules, just shorter. Put each selector on its own line for readability.

In a selector list, one invalid selector makes the browser drop the whole rule. If you write h1, h2, .3col { ... }, the invalid .3col means none of the headings are styled either.

Type plus class

You can combine a type and a class, as in p.intro. That matches only <p> elements with the class intro. It is rarely needed: if the class is well named, .intro is enough, and leaving the type off lets you reuse the class on another element.

A worked example

HTML
<article class="card">
    <h2 class="card-title">Sourdough loaf</h2>
    <p>Slow-fermented for 24 hours.</p>
    <p class="price">£4.20</p>
    <a class="button" href="/basket">Add to basket</a>
</article>
CSS
/* Base styles */
body {
    font-family: system-ui, sans-serif;
    color: #1f2933;
}

h2 {
    margin-top: 0;
}

/* Components */
.card {
    max-width: 20rem;
    padding: 1.5rem;
    border: 1px solid #d9d9d9;
    border-radius: 0.5rem;
}

.card-title {
    font-size: 1.5rem;
}

.price {
    font-weight: 700;
}

.button {
    display: inline-block;
    padding: 0.75rem 1.25rem;
    border-radius: 0.375rem;
    background-color: #0b5394;
    color: white;
    text-decoration: none;
}

Notice the pattern: type selectors for global defaults, classes for each component. That structure scales well.

Debugging selectors

When a rule does nothing:

  1. Inspect the element in DevTools and check its class attribute matches exactly, including case.
  2. Look for a missing dot: button { } targets elements, .button { } targets the class.
  3. Check whether your rule appears in the Styles pane at all. If it does not, the selector does not match.
  4. If it appears but is crossed out, another rule is winning. That is the cascade, covered next.

Summary

  • Type selectors (p) style every element of a type; use them for base styles.
  • Class selectors (.card) are opt-in and reusable; use them for components.
  • ID selectors (#main) target one element and are very strong; avoid them for styling.
  • Group selectors with commas to share declarations, but one invalid selector drops the whole group.
  • Inspect elements in DevTools to check whether a selector matches.

Further reading