On this page
CSS Basic Selectors: Type, Class, ID, Universal & Grouping
CSS Basic Selectors: How to Target HTML Elements
CSS selectors are patterns that tell the browser which HTML elements a rule should style. Without selectors, CSS cannot work: they are the bridge between your HTML and your design. This lesson covers the five basic CSS selectors every developer uses daily: type, class, ID, universal and grouping.
Selector Anatomy Recap
In the rule p { color: blue; }, the part before the curly braces (p) is the selector. The browser scans the DOM, finds every element that matches, and applies the declarations inside the braces.
1. Type Selector (Element Selector)
A type selector matches every element of a given HTML tag name, for example p, h1, a, li, button.
- Syntax: the tag name with no prefix.
- Use it for: global defaults such as body text, headings and links.
- Specificity: very low (0,0,1), so it is easy to override.
- Caution: it affects every matching element on the page, so keep type selectors for broad base styles.
2. Class Selector
A class selector matches elements whose class attribute contains the given name. It starts with a dot.
- Syntax:
.cardmatchesclass='card'. - Reusable: the same class can be used on many elements.
- Combinable: an element can have several classes (
class='btn btn-primary large'). - Compound classes:
.btn.primary(no space) matches elements that have both classes. - Specificity: (0,1,0).
- Best practice: classes are the main tool of modern CSS. Prefer them over IDs for styling.
3. ID Selector
An ID selector matches the single element whose id attribute has the given value. It starts with a hash symbol.
- Syntax:
#headermatchesid='header'. - Unique: an ID must appear only once per page.
- Specificity: high (1,0,0), which makes it hard to override later.
- Best practice: use IDs for anchor links, JavaScript hooks and form labels, but avoid them for styling.
4. Universal Selector
The asterisk matches every element on the page.
- Specificity: zero (0,0,0).
- Most common use: a box-sizing reset (
*, *::before, *::after { box-sizing: border-box; }). - Scoped use:
.sidebar *targets everything inside a sidebar. - Caution: avoid heavy declarations on the universal selector in large pages.
5. Grouping Selector (Selector List)
Separate selectors with commas to apply one set of declarations to several selectors. This keeps your CSS DRY (Don't Repeat Yourself).
h1, h2, h3 { font-family: Georgia, serif; }- Each selector in the list is evaluated independently.
- In modern CSS, a selector list is valid inside :is(), :where() and :not(), and in nested rules.
- Older browsers may drop an entire list if one selector is invalid, but modern forgiving selector lists (inside :is() and :where()) skip only the invalid one.
Comparison Table
| Selector | Example | Matches | Specificity |
|---|---|---|---|
| Universal | * | Every element | 0,0,0 |
| Type | p | All p elements | 0,0,1 |
| Class | .alert | Elements with class alert | 0,1,0 |
| ID | #logo | The element with id logo | 1,0,0 |
| Compound | p.alert | p elements with class alert | 0,1,1 |
| Grouping | h1, h2 | Any selector in the list | Each scored separately |
Combining Basic Selectors
You can combine a type and a class with no space, like a.button, to be more precise. Be careful with the space: .card p means paragraphs inside a card, while .card.p means an element with both classes.
Class vs ID: Which Should You Use?
- Use classes for styling, because they are reusable and keep specificity low and predictable.
- Use IDs for unique hooks: in-page navigation (
href='#contact'), form label associations and JavaScript. - Class names are case-sensitive in standards mode:
.Cardand.cardare different.
Naming Tips
- Use lowercase kebab-case:
.main-nav,.hero-title. - Name by purpose, not appearance:
.alert-errorrather than.red-text. - Consider a naming methodology such as BEM:
.card__title--large. - Class and ID names cannot start with a digit and cannot contain spaces.
Trending Practice: Low-Specificity Architecture
Modern CSS teams keep selectors flat (mostly single classes) so styles are easy to override and refactor. This is also why utility-first approaches such as Tailwind CSS, cascade layers (@layer) and :where() are popular. Understanding the basic selectors well is what makes these tools easy to learn.
Common Mistakes
- Forgetting the dot or hash (writing
cardinstead of.card). - Reusing the same ID on several elements, which is invalid HTML.
- Adding a space in a compound selector and accidentally changing its meaning.
- Overusing the universal selector for expensive declarations.
- Depending on IDs for styling, then needing !important to override them.
Key Takeaways
- Type selectors target tags, classes target reusable groups, IDs target one unique element.
- The universal selector matches everything and has zero specificity.
- Grouping with commas avoids repeated declarations.
- Prefer classes for styling to keep specificity low and CSS maintainable.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Write CSS so that: (1) all paragraphs are dark gray (#444), (2) elements with the class 'notice' have a light yellow background, (3) the element with id 'logo' is 32px in size and bold. Then group h2 and h3 into a single rule with the color teal.
Press Run to execute.
Show expected output
Gray paragraphs, yellow notice background, bold 32px logo, teal h2 and h3.This is a self-check — compare your result with the expected output above.
Make only the paragraph that has BOTH classes 'msg' and 'error' red, and make paragraphs inside the div with class 'panel' italic. Do not affect any other paragraph.
Press Run to execute.
Show expected output
.msg.error { color: red; } .panel p { font-style: italic; }This is a self-check — compare your result with the expected output above.
Was this page helpful?