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

Element Selector
p { }
Targets every instance of an HTML element by its tag name. p targets all paragraphs; h1 targets all top-level headings.
Class Selector
.highlight { }
Targets any element that has a matching class attribute. One class can be applied to many elements of any type.
ID Selector
#hero { }
Targets the single element on a page with a matching 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.

🎨 CSS — Element selectors
/* 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:

🎨 CSS — Universal selector
/* Reset box-sizing on every element */ * { box-sizing: border-box; margin: 0; padding: 0; }
You will see this pattern in almost every real-world stylesheet. box-sizing: border-box makes sizing calculations much more predictable — covered in Chapter 3.
⚠️ Element selectors are broad. Styling 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.

🌐 HTML — Adding a class attribute
<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>
Both the <p> and the <span> have the same class — the CSS rule will apply to both, regardless of their tag name.
🎨 CSS — Class selector
/* 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:

🌐 HTML — Multiple 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>
🎨 CSS — Styles from both classes combine
.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 */
This pattern — a base class plus a modifier class — is the foundation of most CSS architecture methodologies.

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:

Same class applied across different element types
/* 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.

🌐 HTML — The id attribute
<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>&copy; 2026</p> </footer>
🎨 CSS — ID selectors
/* 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; }
⚠️ IDs must be unique. An 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.
IDs have another job: anchor links. The 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
💡 In modern CSS, classes do almost all the styling work. Many experienced developers use IDs only for anchor links and JavaScript hooks, and never for CSS. Classes are more flexible, more reusable, and easier to manage. When in doubt, reach for a class.

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

🎨 CSS — Grouping with commas
/* 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:

🎨 CSS — Element + class combined
/* 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:

🎨 CSS — Requiring two classes at once
/* 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 wordsnav-link, hero-text, btn-primary. This is the standard convention in CSS.
  • Be descriptive but not over-specificcard-title is better than blue-bold-text (the name should describe purpose, not appearance).
  • Do not start with a number2col is invalid. Use col-2 instead.
  • 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.NavLink and .navlink are different selectors. Staying lowercase avoids confusion.
Good vs poor class names
/* 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

SelectorSyntaxHTML to matchTargets
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.

Exercise 1
Create a page with three headings (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.
Hint: group the three heading selectors with commas — h1, h2, h3 { font-family: ... }. Then write separate rules for any per-level differences you want.
styles.css
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; }
Exercise 2
Create a page with a list of five items. Add a 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.
Hint: use text-decoration: line-through for the strikethrough effect.
HTML
<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>
CSS
.done { text-decoration: line-through; color: #999; } .urgent { color: #f08080; font-weight: bold; }
Exercise 3
Build a simple page layout using ID selectors: a <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.
Hint: text-align: center centres text; padding: 20px 40px adds vertical then horizontal padding.
CSS
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; }
Exercise 4
Create a card component using multiple classes. Make a <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.
Hint: use border-left: 4px solid [colour] for the coloured accent border. Chain the class selectors without a space: .card.card-success.
HTML
<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>
CSS
.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.