Basic Selectors
🎯 Chapter 2 — Basic Selectors
A selector is the part of a CSS rule that tells the browser which elements to style. Get selectors wrong and your styles land on the wrong elements — or nowhere at all. This chapter covers the three fundamental selector types: element selectors, class selectors, and ID selectors. These three alone will handle the vast majority of styling you will do early on, and every more advanced selector you learn later is built on top of them.
1 — The Three Basic Selectors at a Glance
p targets all paragraphs; h1 targets all top-level headings.class attribute. One class can be applied to many elements of any type.id attribute. An ID must be unique — only one element per page should carry it.Each selector type has a distinct symbol: element selectors have no prefix, class selectors begin with a dot (.), and ID selectors begin with a hash (#). These characters are part of the CSS syntax, not part of the name itself.
2 — Element Selectors
An element selector (also called a type selector) targets every element on the page that matches a given HTML tag name. Write the tag name — without angle brackets — and the rule applies to all of them.
/* Targets every <h1> on the page */
h1 {
color: #4f8ef7;
font-size: 2rem;
}
/* Targets every <p> on the page */
p {
color: #a0a4b8;
line-height: 1.75;
}
/* Targets every <a> (link) on the page */
a {
color: #7ab8ff;
text-decoration: none;
}
/* Targets every <button> on the page */
button {
background-color: #4f8ef7;
color: white;
border: none;
border-radius: 4px;
padding: 8px 16px;
}
The universal selector
A special case: the asterisk * is the universal selector — it matches every single element on the page. It is most commonly used to apply a global reset:
/* Reset box-sizing on every element */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
box-sizing: border-box makes sizing calculations much more predictable — covered in Chapter 3.p { color: red; } turns every paragraph on the page red — including ones inside navigation menus, footers, or sidebars you did not intend to change. As your pages grow, you will rely more on class selectors for precision.
3 — Class Selectors
A class selector targets elements by a name you invent and assign yourself. You add the class to an HTML element via the class attribute, then select it in CSS with a dot (.) followed by the name.
<p class="highlight">This paragraph has the "highlight" class.</p>
<p>This paragraph has no class — it will not be highlighted.</p>
<span class="highlight">Classes work on any element type.</span>
<p> and the <span> have the same class — the CSS rule will apply to both, regardless of their tag name./* The dot prefix is CSS syntax — "highlight" is the class name */
.highlight {
background-color: #ffd580;
color: #1a1a1a;
padding: 2px 6px;
border-radius: 3px;
}
Multiple classes on one element
An element can carry more than one class — just separate the names with spaces in the class attribute. The element receives the styles from all of its classes:
<p class="card featured">This element has two classes: "card" and "featured".</p>
<p class="card">This element only has the "card" class.</p>
.card {
border: 1px solid #2a2d3a;
border-radius: 6px;
padding: 16px;
background: #1a1d27;
}
.featured {
border-color: #4f8ef7;
border-width: 2px;
}
/* The first paragraph gets BOTH sets of styles — card + featured */
/* The second paragraph gets only the card styles */
One class, many elements
The power of classes is reuse. Define the style once, apply the class to as many elements as you need — of any type:
/* CSS */
.warning-text {
color: #f08080;
font-weight: bold;
}
/* HTML — class applied to different element types */
<p class="warning-text">Warning paragraph.</p>
<span class="warning-text">Warning span inside a sentence.</span>
<li class="warning-text">Warning list item.</li>
4 — ID Selectors
An ID selector targets the one element on a page that has a specific id attribute. In CSS it is written with a hash (#) followed by the ID name.
<header id="site-header">
<h1>My Website</h1>
</header>
<section id="hero">
<p>Welcome to the hero section.</p>
</section>
<footer id="site-footer">
<p>© 2026</p>
</footer>
/* Hash prefix — targets the element with id="site-header" */
#site-header {
background-color: #12141e;
padding: 20px 40px;
border-bottom: 2px solid #4f8ef7;
}
#hero {
min-height: 400px;
display: flex;
align-items: center;
justify-content: center;
}
#site-footer {
background-color: #12141e;
text-align: center;
padding: 20px;
}
id value must appear only once per page. Using the same ID on two elements is invalid HTML and causes unpredictable CSS behaviour. If you need the same styles on multiple elements, use a class instead.
id attribute is also used for in-page navigation — <a href="#hero"> scrolls the page to the element with id="hero". Because of this dual purpose, IDs are best reserved for major page landmarks (header, main, footer, specific sections), not for general styling.
5 — Class vs ID: Which to Use?
Class (.name) |
ID (#name) |
|
|---|---|---|
| How many per element? | Many — an element can have any number of classes | One — an element can only have one ID |
| How many elements can use it? | Unlimited — reuse the same class anywhere | One — must be unique across the whole page |
| CSS specificity | Medium — easily overridden or combined | High — harder to override (more on this in Intermediate) |
| Also used for? | JavaScript (getElementsByClassName) |
Anchor links, JavaScript (getElementById) |
| Best for | Styling — applying visual styles to one or many elements | Page landmarks and JS hooks — not primarily for styling |
6 — Combining Selectors
You can mix and match all three selector types within a single stylesheet, and even combine them in a single rule. Here are three patterns you will use constantly:
Grouping — apply the same rule to multiple selectors
/* Same rule applied to h1, h2, h3, and anything with class "title" */
h1, h2, h3, .title {
font-family: Georgia, serif;
color: #ffffff;
line-height: 1.3;
}
Targeting a specific element type with a class
Write the element name immediately followed by the class name (no space). This targets only elements of that type that also have that class:
/* Only <p> elements with class="lead" — not <div class="lead"> */
p.lead {
font-size: 1.2rem;
font-weight: 500;
}
/* Only <button> elements with class="danger" */
button.danger {
background-color: #f08080;
}
Requiring multiple classes
Chaining two class names (no space, no comma) targets only elements that have both classes:
/* Only elements that have BOTH "card" AND "featured" classes */
.card.featured {
border-color: #ffd580;
box-shadow: 0 0 12px rgba(255, 213, 128, 0.2);
}
/* An element with class="card" alone is NOT targeted */
/* An element with class="card featured" IS targeted */
7 — Naming Your Classes and IDs
Class and ID names can contain letters, numbers, hyphens, and underscores. They are case-sensitive. A few naming rules to follow:
- Use hyphens to separate words —
nav-link,hero-text,btn-primary. This is the standard convention in CSS. - Be descriptive but not over-specific —
card-titleis better thanblue-bold-text(the name should describe purpose, not appearance). - Do not start with a number —
2colis invalid. Usecol-2instead. - Avoid underscores — they work but hyphens are the convention in CSS (underscores are common in BEM methodology, which you will meet in the Intermediate course).
- Keep it lowercase —
.NavLinkand.navlinkare different selectors. Staying lowercase avoids confusion.
/* Poor — describes appearance, not purpose */
.red-text { color: red; }
.big-font { font-size: 2rem; }
.left-column { float: left; }
/* Better — describes purpose, survives a redesign */
.error-message { color: red; }
.page-heading { font-size: 2rem; }
.sidebar { float: left; }
8 — Quick Reference
| Selector | Syntax | HTML to match | Targets |
|---|---|---|---|
| Element | p { } |
<p> |
All <p> elements on the page |
| Universal | * { } |
anything | Every element on the page |
| Class | .card { } |
<div class="card"> |
All elements with class="card" |
| ID | #hero { } |
<section id="hero"> |
The one element with id="hero" |
| Element + class | p.lead { } |
<p class="lead"> |
Only <p> elements that also have class lead |
| Multi-class | .card.featured { } |
<div class="card featured"> |
Elements with both card and featured classes |
| Grouped | h1, h2, .title { } |
any of the above | All matched elements receive the same rule |
✏️ Exercises
For each exercise, create an HTML file with an external stylesheet. Open both files in your editor and the HTML in a browser to see the result. Try each exercise before looking at the solution.
h1, h2, h3) and three paragraphs. Using only element selectors, style the headings with a colour of your choice and the paragraphs with a comfortable line height and a muted text colour. Then use a grouped selector to give all three heading levels the same font family.h1, h2, h3 { font-family: ... }. Then write separate rules for any per-level differences you want.h1, h2, h3 {
font-family: Georgia, serif;
color: #4f8ef7;
}
h1 { font-size: 2rem; }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.2rem; }
p {
line-height: 1.75;
color: #666;
}
class="done" to two of the items and a class="urgent" to one of them. Style .done items with a strikethrough and muted colour, and .urgent items with a bold red colour. The remaining items should have no special styling.text-decoration: line-through for the strikethrough effect.<ul>
<li>Buy groceries</li>
<li class="done">Call the bank</li>
<li class="urgent">Submit tax return</li>
<li class="done">Book dentist</li>
<li>Renew passport</li>
</ul>
.done {
text-decoration: line-through;
color: #999;
}
.urgent {
color: #f08080;
font-weight: bold;
}
<header> with id="site-header", a <main> with id="content", and a <footer> with id="site-footer". Style each section distinctly — different background colours, padding, and text alignment for the footer.text-align: center centres text; padding: 20px 40px adds vertical then horizontal padding.body {
margin: 0;
font-family: Georgia, serif;
}
#site-header {
background-color: #12141e;
color: #ffffff;
padding: 20px 40px;
border-bottom: 3px solid #4f8ef7;
}
#content {
padding: 40px;
background-color: #ffffff;
color: #333;
min-height: 300px;
}
#site-footer {
background-color: #1e2235;
color: #7a7f96;
padding: 16px;
text-align: center;
font-size: 0.85rem;
}
<div> that has a base class of card for a bordered, padded box. Add a second class card-success to one card and card-error to another. Use the combined selector .card.card-success and .card.card-error to give each variant a different left border colour. A third card should have only the card class and show no coloured border.border-left: 4px solid [colour] for the coloured accent border. Chain the class selectors without a space: .card.card-success.<div class="card">
<h3>Default Card</h3>
<p>No status modifier applied.</p>
</div>
<div class="card card-success">
<h3>Success Card</h3>
<p>Payment confirmed.</p>
</div>
<div class="card card-error">
<h3>Error Card</h3>
<p>Something went wrong.</p>
</div>
.card {
border: 1px solid #ddd;
border-radius: 6px;
padding: 16px 20px;
margin-bottom: 12px;
font-family: Georgia, serif;
}
.card.card-success {
border-left: 4px solid #7ecfa0;
}
.card.card-error {
border-left: 4px solid #f08080;
}
This pattern — a base component class with status modifier classes — appears in virtually every real CSS codebase and is the starting point for methodologies like BEM.