Unit 02
The Utility Class
By the end of this unit you can write your own CSS helper classes, restyle a whole page by editing one line, and read a Tailwind class and say exactly what rule it sets.
Unit 1 ended with a stylesheet: rules that pick out elements and change how they look. This unit is about what happens when a page gets big enough that writing a rule per element stops working — you end up editing the same value in nine places and missing the tenth.
The fix is a small idea with a long reach. Write a class that does one thing, name it for the job, and reuse it everywhere that job needs doing. Do that for a whole page and you have built, by hand, exactly what a framework hands you — which is the point. By the end of this unit “utility class” won’t be a term you’ve heard. It’ll be a file you wrote.
One class, one job
Here is the problem, in four lines:
.intro { margin-bottom: 1.5rem; }
.summary { margin-bottom: 1.5rem; }
.footnote { margin-bottom: 1.5rem; }
.aside { margin-bottom: 1.5rem; }
Four rules, one idea, and a fifth place tomorrow that somebody forgets. A utility class A small class that does one job and is reused wherever that job needs doing. — also called a helper — replaces all four:
.stack { margin-bottom: 1.5rem; }
Now the spacing lives in one place. Change it once and every element wearing
.stack changes with it, including the ones you’d have forgotten.
Name it for the job, not the result. .stack still makes sense if the
spacing becomes 2rem. A class called .mb-24px becomes a lie the moment
anybody edits it, and .red becomes a lie the moment the brand colour
changes. The test: would this name still be true if I changed the value?
Add this question to
Loading your meetings…
Which of these helper names will still be honest after a redesign?
A class name is a promise about intent. Names that describe appearance have to be rewritten every time the appearance changes, which is exactly the work helpers were meant to save.
Write your own. Two helpers, applied to elements that have nothing else in common — that’s the whole idea, proved on a real page.
Write it · html
Renders as you type · nothing leaves your browser
Two helpers, used twice each.
Tab indents. Press Esc first to tab out of the box.
Result
- A .stack helper that sets exactly one property Spacing below an element. One declaration and no more.
- A .lede helper that sets exactly one property Something that makes an opening line read as an opening line — size, weight, or colour.
- .stack is used on at least two elements
- .lede is used on at least two elements
- Still no styles in the markup
Notice what you did not have to do: you never wrote a rule about the h2, or about that particular paragraph. You described two jobs and then said which elements need them.
A palette in custom properties
Helpers solve repetition inside one property. Custom properties A named value declared once in CSS and read anywhere with var(). solve it across properties — the same colour used by a heading, a border, and a button.
Declare them once, at the top, on :root:
:root {
--brand: #b4513a;
--ink: #221c1a;
}
.banner { color: var(--brand); }
.rule { border-top: 2px solid var(--brand); }
Now --brand is the single place the colour lives. Change that one line and
the heading, the border and anything else reading it all move together. This
is the mechanism behind every “theme” you have ever switched — and it is the
same idea you’ll use in Unit 5 to force a template’s buttons into your own
palette.
Add this question to
Loading your meetings…
Why declare custom properties on :root rather than on the elements that use them?
Custom properties follow the same inheritance rules as colour and font. Declaring at the root is just choosing the widest possible scope, on purpose.
Write it · css
Renders as you type · nothing leaves your browser
One line changes the whole page.
styles.css
Tab indents. Press Esc first to tab out of the box.
Result
- A palette declared on :root Custom properties start with two dashes: --brand: #b4513a;
- .banner reads a custom property instead of a literal colour
- .rule reads the same custom property
The HTML is fixed for this one — only the stylesheet is yours. That is the argument in miniature: the markup did not change, and the page looks completely different.
Composing without cascade fights
Helpers are meant to stack. An element can wear three of them, and if each sets a different property nothing collides:
<p class="stack lede muted">An opinionated list.</p>
Trouble starts when two helpers set the same property. Then the winner is decided by the rules you learned in Unit 1 — specificity first, file order as the tiebreak — and the answer depends on the stylesheet rather than on the markup you are looking at.
Add this question to
Loading your meetings…
Your stylesheet has .muted { color: grey } and .warn { color: red }, and someone writes class="muted warn". What is actually wrong here?
A helper system works because reading the class list tells you the result. Two helpers setting one property break that promise, and the cascade quietly picks a winner you did not choose.
Add this question to
Loading your meetings…
A helper .muted { color: grey } refuses to work on
because the stylesheet also has article p { color: black }. What is the right fix?
A single class selector is weak on purpose. If your helpers keep losing, the problem is almost always a base rule that is more specific than it needed to be.
What a framework hands you
You have now written a file of small, single-purpose, well-named classes. That file has a name in the industry: a utility framework. Tailwind CSS is that file, written by other people, at a scale no one person would maintain — and daisyUI is a set of ready-made components built on top of it.
So the classes are not new to you. Only the names are:
| Tailwind class | The rule it sets | Your version |
|---|---|---|
p-4 | padding: 1rem | a helper you named for the job |
flex | display: flex | same idea, one property |
gap-4 | gap: 1rem | same idea, one property |
text-center | text-align: center | same idea, one property |
mb-6 | margin-bottom: 1.5rem | your .stack, generalised |
Add this question to
Loading your meetings…
You meet
Every Tailwind class is a helper that sets one property. Once you can read the naming system you can read the markup, and none of the underlying CSS is new.
Reading the naming system and writing it are different skills. Try it:
Write it · html
Renders as you type · nothing leaves your browser
Same three helpers, Tailwind's names.
index.html
Tab indents. Press Esc first to tab out of the box.
Result
- A flex container class="flex" on the div around the three paragraphs.
- A gap between the children
- Padding inside the box
Composing three helpers is composing three helpers, whoever named them. Try a class that is not in the table above (grid, say) and nothing happens — this exercise ships a small, fixed set on purpose. A real Tailwind build generates whatever you actually use, which is what the next callout is about.
The trade
Frameworks are not free and they are not a trap. They are a trade, and being able to name both sides of it is the actual skill.
| Your own helper file | A utility framework | |
|---|---|---|
| Reading the markup | One well-named class says the intent | Fifteen classes on one element say the details |
| Consistency | Only as consistent as you are | A designed scale you cannot drift off |
| Someone joining | They must learn your names | They probably already know these |
| Setup | A file you link | A build step |
| What ships | Exactly what you wrote | Exactly what you used, generated |
Submit for review · text
Read by a human · you can resubmit
You wrote a helper file in this unit. Argue for when you would keep writing your own and when you would reach for Tailwind instead. Quote at least one class from your own stylesheet as evidence, and name one thing the framework would genuinely have done better.
What earns points5 pts
- 2 Cites their own stylesheet specifically
- 2 Names a real advantage of the framework
- 1 Reaches a defensible position rather than "it depends"
Anyone can say 'it depends.' The skill is saying what it depends on, with a line of your own CSS in front of you as the example.
That’s the unit: one class, one job (WD2.1); the values behind the classes,
named once (WD2.2); several helpers on one element without a fight
(WD2.3); and the same objects at industrial scale, wearing someone else’s
names (WD2.4). Unit 3 stops describing utility classes and starts building
a real, responsive page out of them.
Where you are
Not startedAnswer the checks above whenever you like. They're not graded, and you can retry any of them.
Kept in this browser only, unless you sign in.
Signing in carries this — and everything else you've done here — onto any device, and keeps it if you clear this browser.
Sources
- Gilmour Academy — Intro to Web Design
Intro to Web Design · members' unit
The Utility Class is behind a locked door
Units in Intro to Web Design are for people taking the course. Getting in takes a link or a key — signing in on its own doesn't do it.
What's in this unit · 11 min read
- One class, one job
- A palette in custom properties
- Composing without cascade fights
- What a framework hands you
- The trade
5 quick checkslive HTML/CSS sandboxcode exercises
1 Sign in
With your school Google account. This is how your work reaches the gradebook — it doesn't open the unit by itself.
A key unlocks this browser and keeps your progress here; signing in keeps it with you across devices. Either way the key itself is only ever checked as a hash. Manage all of this on your account, read what signing in stores, or go back to Intro to Web Design.
Connecting…
Who said what
Yours to act on, not to read out. The class only ever sees the shape of the answers, with no names on them.
Your teacher is presenting. While this marker is showing, your name is visible to them, so they can see who's connected — nothing about which page you're on, what you're doing, or how you're scrolling is sent. If they ask a check-in and you answer, that answer is sent too. What's stored