Lesson 28 / Systems
Design Systems
Create a mini design system with reusable colors, spacing, typography, buttons, cards, forms, navigation, states, and accessibility rules for a consistent project.
Course Role
Studio Support
Best during work sessions, critique, debugging, project planning, or final polish.
Teacher Notes / In-Class Use
Demo Live
- Walk through the interactive demo before students start changing their own project files.
- Connect the demo back to the first goal: Explain what a small project design system does
Try In Class
- Identify three repeated patterns in your project.
- Have students make one visible change, save, refresh, and explain what changed.
Submit Or Check
- Ask students to show the work in the browser, not only in the editor.
- Have students commit their progress with a clear message when the checkpoint is stable.
Watch For
- Students copying code without checking file paths, spelling, or capitalization.
- Visual changes that work locally but break when the project is published.
Learning Goals
- Explain what a small project design system does
- Define reusable tokens for color, type, spacing, radius, borders, and shadows
- Build consistent buttons, cards, forms, containers, and navigation patterns
- Audit a project for one-off styles and refactor them into reusable components
Interactive Demo
How to use this demo.
Use the demo as a small lab. Change one thing, observe the result, then connect it back to your own project.
What To Try
- Change the accent, radius, and spacing tokens.
- Watch the card, button, and input update from the same reusable values.
What Changes
- One token change affects multiple components at once.
- The generated CSS shows the custom properties behind the visual system.
What To Notice
- Design systems reduce one-off styling by giving repeated decisions a shared name.
- Tokens should describe design decisions that repeat across the project.
Apply It
- Create a small :root token set for colors, spacing, and radius in your own project.
Interactive Demo
Design System Token Lab
Adjust a few reusable values and watch multiple components update together.
Featured
Reusable Card
The card, button, and form field share the same tokens.
:root { --accent: #73d36b; } This demo uses extra JavaScript for teaching. The code sample shows the pattern to practice. View full demo source.
Design Systems in Student Terms
A small design system is the reusable visual and code rules for your project. It helps the site feel intentional instead of like every page was styled separately.
For class projects, a design system does not need to be huge. Start with shared colors, type, spacing, buttons, cards, forms, navigation, layout containers, and states.
What Belongs in a Mini Design System
| Part | Decisions To Make |
|---|---|
| Colors | Background, text, brand, accent, border, muted text, success, warning, and error colors. |
| Typography | Font families, heading scale, body size, line height, and font weights. |
| Spacing | Reusable spacing values for sections, cards, grids, and form fields. |
| Components | Buttons, cards, forms, navigation, badges, and layout containers. |
| States | Hover, focus, active/current, disabled, loading, error, and success states. |
| Accessibility | Contrast, visible focus, semantic HTML, labels, and keyboard-friendly controls. |
Design Tokens
Tokens are named values. They make design decisions easier to reuse and easier to change later.
Use names that describe purpose when possible. --color-brand is more useful than --blue because the brand color may change later.
:root {
--color-background: #ffffff;
--color-surface: #f7f7f4;
--color-text: #111111;
--color-muted: #5f635f;
--color-brand: #2f6fed;
--color-border: #d8ddd8;
--color-error: #b42318;
--font-body: system-ui, sans-serif;
--font-display: Georgia, serif;
--space-1: 0.5rem;
--space-2: 1rem;
--space-3: 1.5rem;
--space-4: 2rem;
--radius-sm: 0.25rem;
--radius-md: 0.5rem;
--shadow-card: 0 0.75rem 2rem rgb(0 0 0 / 0.08);
} Naming Guidance
| Avoid | Prefer | Why |
|---|---|---|
--blue | --color-brand | Purpose survives if the color changes. |
--big-space | --space-4 or --space-lg | A scale keeps spacing consistent. |
.big-blue-button | .button-primary | Role matters more than appearance. |
.left-box | .sidebar or .card-aside | Names should explain the component or purpose. |
Button Component
A button component should include spacing, color, hover, focus, and disabled states. Use a real button for actions and an a element for navigation links.
<a class="button button-primary" href="/projects/">View projects</a>
<button class="button button-secondary" type="button">Save draft</button>
.button {
align-items: center;
border-radius: var(--radius-md);
display: inline-flex;
font-weight: 800;
gap: 0.5rem;
min-block-size: 2.75rem;
padding: 0.75rem 1rem;
text-decoration: none;
}
.button-primary {
background: var(--color-brand);
color: #ffffff;
}
.button-secondary {
background: var(--color-surface);
border: 1px solid var(--color-border);
color: var(--color-text);
} Card Component
Cards should use consistent padding, border, image ratios, heading size, and link behavior. A card is a repeated content pattern, not just a decorative box.
<article class="card">
<img class="card-image" src="project.jpg" alt="Homepage design for a restaurant guide">
<div class="card-body">
<h2 class="card-title">Restaurant Guide</h2>
<p>A responsive listing project for local restaurants.</p>
<a href="/projects/restaurant-guide/">View project</a>
</div>
</article>
.card {
background: var(--color-background);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
overflow: hidden;
}
.card-image {
aspect-ratio: 16 / 9;
object-fit: cover;
width: 100%;
}
.card-body {
display: grid;
gap: var(--space-1);
padding: var(--space-2);
} Form Field Component
Form styles should include labels, help text, errors, and focus states. Do not rely on placeholder text as the only label.
<div class="form-field">
<label for="email">Email address</label>
<input id="email" name="email" type="email" aria-describedby="email-help">
<p id="email-help">Use the email address you check most often.</p>
</div>
.form-field {
display: grid;
gap: 0.4rem;
}
.form-field input {
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
font: inherit;
padding: 0.75rem;
} Layout Container
A reusable container keeps page content aligned across sections. It is one of the simplest ways to make a site feel consistent.
.container {
margin-inline: auto;
max-width: 72rem;
padding-inline: var(--space-2);
}
.section {
padding-block: var(--space-4);
} States Are Part of the System
A component is not complete if it only covers the default state. Include the states users will actually encounter.
| State | System Decision |
|---|---|
| Hover | How links and buttons respond to pointer interaction. |
| Focus | Visible keyboard focus style for links, buttons, and form fields. |
| Active/current | How current navigation or selected filters are shown. |
| Disabled | How unavailable actions look without disappearing. |
| Error | How form fields communicate what needs to be fixed. |
| Success | How completed actions are confirmed. |
:focus-visible {
outline: 3px solid var(--color-brand);
outline-offset: 3px;
}
.button-primary:hover {
filter: brightness(0.92);
}
.button:disabled {
cursor: not-allowed;
opacity: 0.55;
} Accessibility Rules
- Use semantic HTML before creating custom controls.
- Keep text and button contrast readable.
- Include visible focus styles in every interactive component.
- Use
labelelements for form controls. - Do not make every component a generic
div. - Test reusable components with keyboard input, not only a mouse.
Before and After Refactor
Design systems often begin by noticing repeated one-off styles and turning them into reusable classes.
/* Before: every card has its own style */
.homepage-card {
border: 1px solid #ddd;
padding: 20px;
}
.project-card {
border: 1px solid #ddd;
padding: 20px;
}
/* After: shared component plus optional modifier */
.card {
border: 1px solid var(--color-border);
padding: var(--space-2);
}
.card-featured {
box-shadow: var(--shadow-card);
} Audit Your Project
Before building new styles, inspect what already exists. Your first design system task is often reducing inconsistency.
| Audit Question | What To Look For |
|---|---|
| How many button styles exist? | Repeated button CSS that could become .button and modifiers. |
| Are card paddings consistent? | Cards with different spacing values for no clear reason. |
| Are headings using the same scale? | Random font sizes instead of a type system. |
| Are colors repeated directly? | Hex values repeated throughout CSS instead of tokens. |
| Are focus states consistent? | Some components with focus styles and others without. |
Mini Style Guide Deliverable
A style guide page or section makes the system visible. It does not need to be fancy; it needs to show the decisions clearly.
- Color swatches with token names.
- Heading and body text examples.
- Primary and secondary buttons, including hover and focus states.
- A card component with real content.
- A form field with label, help text, and error state.
- Navigation or link styles.
Common Mistakes
| Mistake | Fix |
|---|---|
| Creating a new button style for every page | Create a shared .button class and modifier classes. |
| Using colors directly everywhere | Move repeated values into custom properties. |
| Changing spacing one element at a time | Use a spacing scale. |
| Making components visually consistent but semantically weak | Use correct HTML and accessibility behavior. |
| Building a huge system before the project needs it | Start with the patterns your project actually uses. |
Checkpoint
Before moving on, make sure these feel true.
- I can define reusable color, spacing, and type values.
- I can create consistent button, card, and form styles.
- I can reduce one-off styling in a project.
Practice
- Identify three repeated patterns in your project.
- Create reusable classes for buttons, cards, and form fields.
- Replace repeated color and spacing values with named custom properties.
- Add hover, focus, and disabled states to one button component.
- Create a mini style guide section showing colors, type, buttons, cards, and form fields.
- Refactor one pair of one-off styles into a shared component class and modifier.