HTML & CSS · Lesson 3 of 5
CSS Basics
Selectors, the cascade, the box model, colors and typography.
- Beginner
- 16 min read
- 3 objectives
Before this lessonLesson 2: Forms and Semantic HTML
What you will learn
- Write selectors
- Explain specificity
- Use the box model
CSS (Cascading Style Sheets) controls how HTML looks: colors, fonts, spacing and layout. A rule has a selector (what to style) and declarations (how to style it).
What CSS does
HTML says what content is; CSS (Cascading Style Sheets) says how it looks: colours, fonts, spacing, layout. The same HTML can look like a plain document or a polished app depending on the stylesheet attached. Keeping them separate is the big idea: one CSS file can restyle a thousand pages.
A CSS rule has two parts: a selector that says which elements, and a block of declarations that say what to change.
h1 { /* selector: every <h1> */
color: navy; /* property: value; */
font-size: 2rem;
}h1 {
color: #0a0a0a;
font-size: 2rem;
}Link a stylesheet from the head of your page: <link rel="stylesheet" href="styles.css">.
Selectors
p { } /* every paragraph */
.card { } /* elements with class="card" */
#hero { } /* the element with id="hero" */
nav a { } /* links inside nav */
ul > li { } /* direct children only */
a:hover { } /* when hovered */
input:focus-visible { } /* keyboard focus */
button[disabled] { } /* attribute selector */Prefer classes for styling. IDs are too specific, and element selectors are too broad.
The cascade and specificity
When rules conflict, CSS picks a winner: the more specific selector wins (ID beats class beats element), and if specificity is equal, the rule that comes later wins. Some properties are also inherited by children, such as color and font-family. Avoid !important; it makes styles hard to override and debug.
The box model
Every element is a box made of content, padding (space inside), border and margin (space outside). By default, width covers only the content, so adding padding makes the box larger. Almost every stylesheet begins by fixing that:
*, *::before, *::after {
box-sizing: border-box; /* width includes padding and border */
}
.card {
width: 300px;
padding: 1rem;
border: 1px solid #ddd;
border-radius: 8px;
margin: 0 auto 1.5rem;
}Units and colors
px: fixed pixels.rem: relative to the root font size (great for accessible sizing).em: relative to the current font size.%,vw,vh: relative to the parent or the viewport.- Colors: names (
tomato), hex (#ff6347),rgb(),hsl().
Typography
body {
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
font-size: 1rem;
line-height: 1.6;
color: #222;
}
h1 { font-weight: 700; letter-spacing: -0.02em; }Custom properties
CSS variables keep values consistent and make theming easy.
:root {
--brand: #2563eb;
--radius: 8px;
}
.button {
background: var(--brand);
border-radius: var(--radius);
color: white;
padding: 0.6rem 1.2rem;
}
.button:hover { filter: brightness(1.1); }Connecting CSS to HTML
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1 class="title">Hello</h1>
<p class="lead">Welcome to my page.</p>
<p>A normal paragraph.</p>
</body>/* styles.css */
body {
font-family: system-ui, sans-serif;
line-height: 1.6;
color: #1f2937;
}
.title { /* a class selector starts with a dot */
color: #0f766e;
}
.lead {
font-size: 1.25rem;
color: #475569;
}The box model: everything is a box
Every element is a rectangle made of four layers. From the inside out: the content, padding (space inside the border), the border and margin (space outside, separating it from neighbours). Once you can see these boxes in your head, layout stops being mysterious.
.card {
width: 300px;
padding: 16px; /* inside space */
border: 1px solid #cbd5e1;
margin: 24px auto; /* outside space; auto centres horizontally */
border-radius: 12px;
box-sizing: border-box; /* width includes padding and border: much easier to reason about */
}Why is my rule not working?
- Specificity: an ID selector beats a class, which beats an element selector. A more specific rule wins regardless of order.
- Order: when two rules are equally specific, the later one wins.
- Typos: an unknown property or a missing semicolon silently makes the browser skip the rule.
- Inspect the element: struck-through declarations show which rule lost.
Key takeaways
- A rule is a selector plus declarations:
selector { property: value; }. - Select by element,
.classor#id; prefer classes. - Every element is a box: content, padding, border, margin; use
box-sizing: border-box. - Use DevTools to see which rules apply and to experiment live.
// Write your solution here
