CSS
CSS controls how your HTML looks: color, spacing, typography, layout. It doesn’t change the structure of your document. It describes how that structure should be presented.
That distinction matters because it’s what keeps your code maintainable. When you need to change a color, you go to CSS. When you need to add a section, you go to HTML. The two concerns don’t bleed into each other.
Create a stylesheet
In the VS Code sidebar, right-click the src folder and select New File. Name it style.css. Or from the integrated terminal:
touch src/style.cssThen link it to your HTML. Add this line inside the <head> of index.html, after your <meta> tags:
<link rel="stylesheet" href="style.css" />Save both files. Anything you write in style.css now applies to index.html. The Live Preview panel will reflect your changes as you save.
How CSS works
A CSS rule has two parts: a selector and a declaration block.
p {
color: #333333;
line-height: 1.6;
}p is the selector. It targets every <p> element on the page. The declarations inside the curly braces describe how those elements should look. Each declaration is a property (color) and a value (#333333), separated by a colon, ended with a semicolon.
VS Code’s IntelliSense will suggest property names and valid values as you type. It’s useful while you’re building familiarity with CSS syntax.
Selectors
You’ll use three kinds most often.
Element selectors target every instance of an HTML element:
h1 {
font-size: 2rem;
}Class selectors target elements with a specific class attribute. They start with .:
.intro {
font-size: 1.2rem;
}To use this, add class="intro" to an element in your HTML:
<p class="intro">This paragraph gets the intro styles.</p>ID selectors target a single element with a specific id. They start with #:
#main-content {
max-width: 800px;
}In practice, IDs in CSS are something to use sparingly. They carry higher specificity than classes, which makes them harder to override. For most styling, classes are the right tool. MDN has a thorough explanation of CSS selectors worth reading once you’re comfortable with the basics.
The cascade
CSS stands for Cascading Style Sheets. The cascade is the algorithm browsers use to decide which rule wins when multiple rules target the same element.
Three things determine which rule wins: specificity, order, and inheritance.
Specificity is a weight assigned to each selector. ID selectors outweigh class selectors, which outweigh element selectors. When two rules conflict, the more specific one wins:
p {
color: black; /* lower specificity */
}
.intro {
color: green; /* higher specificity, wins on elements with class="intro" */
}Order is the tiebreaker. When two rules have identical specificity, the one appearing later in the stylesheet wins.
Inheritance means some CSS properties automatically pass from parent elements to their children. color and font-family inherit. border and padding do not. When you set font-family on body, every element inherits it unless something overrides it.
Understanding the cascade is what separates developers who fight their own CSS from developers who don’t. When a style isn’t applying as expected, specificity is usually why. MDN’s cascade, specificity, and inheritance article is the definitive explanation.
The box model
Every HTML element is a rectangular box with four layers:
- Content: the text or image inside the element
- Padding: space between the content and the border
- Border: the border itself
- Margin: space outside the border, between this element and its neighbors
p {
padding: 16px;
border: 1px solid #cccccc;
margin: 24px 0;
}By default, browsers calculate element width as content width only, adding padding and border on top of that. This makes sizing unintuitive. One line fixes it:
*,
*::before,
*::after {
box-sizing: border-box;
}With border-box, padding and border are included in an element’s declared width. Set width: 300px and the element is 300px wide, border and padding included. Add this to the top of every stylesheet you write.
CSS custom properties
CSS custom properties (also called CSS variables) let you store values and reuse them throughout your stylesheet. They’re defined on a selector, typically :root so they’re globally available, and referenced with var().
:root {
--color-text: #1a1a1a;
--color-accent: #2a6496;
--font-body: Georgia, serif;
--spacing-md: 24px;
}
body {
color: var(--color-text);
font-family: var(--font-body);
}
a {
color: var(--color-accent);
}
section {
margin-bottom: var(--spacing-md);
}The convention is to prefix custom property names with --. When you build a WordPress theme later in this series, you’ll define your entire design system this way: colors, spacing, typography, all in one place. Change a value in :root and it updates everywhere it’s referenced.
Style the project page
Add this to style.css. Prettier will format it on save.
/* Reset */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* Tokens */
:root {
--color-bg: #ffffff;
--color-text: #1a1a1a;
--color-muted: #555555;
--color-accent: #2a6496;
--font-body: Georgia, serif;
--font-ui: system-ui, sans-serif;
--spacing-sm: 12px;
--spacing-md: 24px;
--spacing-lg: 48px;
--max-width: 720px;
}
/* Base */
body {
background-color: var(--color-bg);
color: var(--color-text);
font-family: var(--font-body);
line-height: 1.7;
padding: var(--spacing-lg) var(--spacing-md);
}
/* Layout */
main {
max-width: var(--max-width);
margin: 0 auto;
}
/* Typography */
h1 {
font-size: 2rem;
line-height: 1.2;
margin-bottom: var(--spacing-md);
}
h2 {
font-size: 1.4rem;
line-height: 1.3;
margin-top: var(--spacing-lg);
margin-bottom: var(--spacing-sm);
}
p {
margin-bottom: var(--spacing-md);
color: var(--color-muted);
}
/* Navigation */
nav {
font-family: var(--font-ui);
margin-bottom: var(--spacing-lg);
}
nav ul {
list-style: none;
display: flex;
gap: var(--spacing-md);
}
nav a {
color: var(--color-accent);
text-decoration: none;
}
nav a:hover {
text-decoration: underline;
}
/* Lists */
ul,
ol {
padding-left: var(--spacing-md);
margin-bottom: var(--spacing-md);
}
li {
margin-bottom: var(--spacing-sm);
}
/* Footer */
footer {
margin-top: var(--spacing-lg);
padding-top: var(--spacing-md);
border-top: 1px solid #dddddd;
font-family: var(--font-ui);
font-size: 0.875rem;
color: var(--color-muted);
}Save and look at the Live Preview. You now have a readable, structured page with a consistent spacing scale and a token system that carries forward into every chapter from here.
Commit your work
git add .
git commit -m "Add stylesheet with base styles and design tokens"What you now know
You understand selectors, the cascade, the box model, and CSS custom properties. The design token pattern you’ve started here scales into production. You’ll use it in the WordPress theme at the end of this series. In Chapter 6 you’ll add JavaScript and start making the page interactive.
Reference
- MDN: CSS basics
- MDN: CSS reference
- MDN: Cascade, specificity, and inheritance
- MDN: The box model
- MDN: Using CSS custom properties
- MDN: CSS selectors