Module 0.5

Modern CSS Quick Reference for React Beginners

2–3 hr · Read + practice

CSS turns the HTML structure of your app into the visual interface users actually see. Every box, every color, every spacing decision, every layout in React is ultimately CSS. This reference covers the foundations you need to read and write CSS confidently for the program — and what each concept maps to in Tailwind CSS, the utility-class system we use daily from Week 1 onward.

Every section has a snippet you can paste straight into the browser DevTools (right-click anything on a page → Inspect → Elements panel → edit the Styles pane on the right) to see the effect live. Don’t just read — type, change values, watch what breaks. That’s how CSS becomes reflexive. You’ll meet DevTools in detail in the Browser DevTools Tour.


1. The Box Model

Every HTML element is a rectangular box. The box has four concentric layers, each contributing to its total size:

┌──────────────── margin ────────────────┐
│ ┌────────────── border ──────────────┐ │
│ │ ┌──────────── padding ───────────┐ │ │
│ │ │           content              │ │ │
│ │ └────────────────────────────────┘ │ │
│ └────────────────────────────────────┘ │
└────────────────────────────────────────┘

CSS for each:

.card {
  width: 300px;
  padding: 16px;
  border: 1px solid #ccc;
  margin: 24px;
}

By default, width only sets the content width — padding and border are added on top. So width: 300px + padding: 16px (×2 sides) + border: 1px (×2 sides) = actual rendered width of 334px. This is rarely what you want.

The fix is box-sizing: border-box:

* {
  box-sizing: border-box;
}

.card {
  width: 300px;          /* now includes padding + border */
  padding: 16px;
  border: 1px solid #ccc;
}
/* Card renders at exactly 300px wide */

This is the universal modern default. Every CSS reset, every Tailwind project, every Next.js starter includes it.

Tailwind equivalent: w-[300px] p-4 border border-gray-300 m-6 (where p-4 = 1rem = 16px in the default theme; box-sizing: border-box is preset).

Why this matters in React: Every component you build sits in a box. When components don’t line up, it’s almost always a box-model misunderstanding — usually padding or border pushing things wider than expected. Lean on padding (inside the box) over margin (outside) when you can — it composes more predictably.


2. Selectors and Specificity

CSS rules need to target elements. A selector says which elements to style.

/* Type / element selector */
button { background: #007aff; }

/* Class selector — most common */
.btn-primary { background: #007aff; }

/* ID selector — rare in modern React */
#hero { background: #f4f4f4; }

/* Descendant — any .btn anywhere inside .toolbar */
.toolbar .btn { margin-left: 8px; }

/* Child — only .btn that's a direct child of .toolbar */
.toolbar > .btn { margin-left: 8px; }

/* Attribute selector */
input[type="email"] { font-family: monospace; }

Pseudo-classes match elements in a particular state:

.btn:hover    { background: #0055cc; }
.btn:focus    { outline: 2px solid blue; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
a:visited     { color: purple; }
li:first-child { margin-top: 0; }

Pseudo-elements style a piece of the element:

.required::after { content: " *"; color: red; }
::placeholder    { color: #999; }

Specificity decides which rule wins when two target the same element. From strongest to weakest:

  1. Inline style="..." attribute
  2. #id selectors
  3. .class, [attribute], :pseudo-class selectors
  4. tag, ::pseudo-element selectors

So .btn.primary (two classes) beats button (one tag); #submit beats .btn; style="..." beats every other selector — but don’t reach for inline styles or !important to win specificity fights. Restructure the selector instead.

Tailwind: Tailwind sidesteps specificity by giving every utility class the same low specificity (one class each). The cascade order in your HTML decides which one wins, which is much easier to reason about than nested rules.

Why this matters in React: In modern React you rarely write complex selectors by hand — Tailwind’s utility classes target individual elements directly. But you’ll still read existing CSS in third-party components and use pseudo-classes constantly. hover:bg-blue-700 in Tailwind expands to :hover { background: ... } in CSS.


3. Display — Block vs Inline vs Flex vs Grid

The display property controls how an element flows on the page. The values you’ll meet:

.row {
  display: flex;          /* lay children horizontally */
}

.card-grid {
  display: grid;          /* lay children as a grid */
  grid-template-columns: repeat(3, 1fr);
}

.hidden {
  display: none;          /* removes from the layout entirely */
}

Tailwind: block, inline-block, inline, flex, grid, hidden.

Why this matters in React: Every component’s outermost element gets a display mode (often flex or grid). Knowing how each one flows prevents the universal beginner bug of “why isn’t my element next to the other one?“


4. Flexbox — One-Dimensional Layout

Flexbox is the layout system you’ll use for almost every component-internal layout. The container gets display: flex; its direct children become flex items.

<div class="row">
  <div>A</div>
  <div>B</div>
  <div>C</div>
</div>
.row {
  display: flex;
  gap: 12px;                       /* space between children */
  justify-content: space-between;  /* horizontal distribution */
  align-items: center;             /* vertical alignment */
}

Container properties

Item properties

Common patterns

Horizontal toolbar with even spacing:

.toolbar {
  display: flex;
  gap: 8px;
}

Page-level vertical stack with main taking remaining space:

.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.page > main {
  flex: 1;               /* main fills the gap between header and footer */
}

Card with text on the left and a button pinned to the right:

.card {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

Tailwind: flex, flex-col, gap-2, justify-between, items-center, flex-1. Every Tailwind project is mostly flex utilities.

Why this matters in React: Every header bar, every card row, every form layout, every nav menu — flexbox. By Week 2 you’ll write flex items-center justify-between gap-4 reflexively.


5. Grid — Two-Dimensional Layout

Where flexbox handles one row or one column, CSS Grid lays out items in a two-dimensional grid.

<div class="grid">
  <div>A</div> <div>B</div> <div>C</div> <div>D</div>
</div>
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);  /* 3 equal-width columns */
  gap: 16px;
}

The fr unit is “fraction of remaining space” — 1fr 2fr 1fr makes the middle column twice as wide as the sides.

Common patterns

Sidebar + main content:

.app {
  display: grid;
  grid-template-columns: 240px 1fr;
  min-height: 100vh;
}

Responsive card grid that automatically reflows on smaller screens — no media queries needed:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
}

That auto-fill + minmax() pattern is a workhorse: each card stays at least 280px wide and the browser packs as many per row as fit.

Tailwind: grid, grid-cols-3, gap-4, and grid-cols-[240px_1fr] for arbitrary tracks.

Why this matters in React: Page-level layouts (sidebar + main, dashboard tiles, photo galleries) use Grid; component-internal layouts use Flex. Mixing both on the same page is normal and expected.


6. Positioning

The position property takes an element out of normal flow and lets you place it precisely.

.tooltip {
  position: absolute;
  top: 0;
  left: 100%;
}

The five values:

The classic pattern is relative parent + absolute child — the child stays anchored to a spot inside the parent:

.avatar { position: relative; }
.avatar .badge {
  position: absolute;
  top: -4px;
  right: -4px;
}

z-index controls stacking order when boxes overlap. Higher number = on top. Only works on positioned elements. Common values: 0 (default), 10 (dropdowns), 100 (modals), 1000 (toasts).

Tailwind: relative, absolute, fixed, sticky, top-0, right-2, z-10.

Why this matters in React: Modals, dropdowns, tooltips, image overlays, toast notifications — they all rely on positioning. The relative parent + absolute child pattern is the foundation of half of them.


7. Colors, Typography, and Spacing

Colors

.card {
  color: #1a1a1a;              /* text */
  background-color: #ffffff;   /* fill */
}

Color formats:

Typography

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 16px;
  line-height: 1.5;
  color: #1a1a1a;
}

h1 {
  font-size: 2.5rem;     /* 40px when root is 16px */
  font-weight: 600;
  letter-spacing: -0.015em;
}

Units — when to use what

The convention: rem for fonts and spacing, px for borders and tiny details, % and fr for layout.

Spacing scale

Pick a consistent scale. Tailwind defaults to multiples of 4px: 4, 8, 12, 16, 24, 32, 48, 64. Use it for padding, margin, gap. Don’t invent arbitrary values like 13px or 27px — your UI will look amateur.

Tailwind: text-base, font-semibold, text-gray-900, bg-white, p-4, m-6.

Why this matters in React: Design tokens — a fixed color palette and a fixed spacing scale — are what make a UI look professional vs. amateur. Stick to your scale; resist the urge to invent values.


8. Responsive Design

Modern web apps work on any screen size. The convention is mobile-first: write the baseline styles for small screens, then add @media rules to adjust for larger ones.

/* Mobile (default): single column */
.cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}

/* Tablet (≥768px): two columns */
@media (min-width: 768px) {
  .cards {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* Desktop (≥1024px): three columns */
@media (min-width: 1024px) {
  .cards {
    grid-template-columns: repeat(3, 1fr);
  }
}

Common breakpoints (Tailwind’s defaults — adopt them unless you have a reason not to):

NameMin-width
sm640px
md768px
lg1024px
xl1280px
2xl1536px

Don’t forget the viewport meta tag in your HTML <head> (Next.js adds this automatically):

<meta name="viewport" content="width=device-width, initial-scale=1" />

Without it, mobile browsers render your page at desktop width and zoom out — your layout will look tiny and broken on a phone.

Tailwind: grid-cols-1 md:grid-cols-2 lg:grid-cols-3 — read as “one column by default, two at md and up, three at lg and up.” Three media queries in one line.

Why this matters in React: Your capstone has to look reasonable on a phone (judges scan from Demo Day audience seats). Use the DevTools mobile emulator (Cmd + Shift + M) to test as you build, not as a final-day polish.


9. The Cascade and CSS Variables

The cascade

When two CSS rules target the same element with the same specificity, the later one wins:

.btn { background: blue; }
.btn { background: red; }      /* wins — button is now red */

When specificities differ, higher specificity wins (see §2). Combined with the !important hammer (don’t use it) and inline styles, this is “the cascade.”

CSS variables (custom properties)

Declare a variable with --name, use it with var(--name):

:root {
  --color-primary: #0c1e3d;
  --color-accent: #21a79b;
  --space-md: 1rem;
}

.btn {
  background: var(--color-primary);
  padding: var(--space-md);
}

.btn:hover {
  background: var(--color-accent);
}

Variables enable theming (dark mode, brand customization) and design tokens:

body[data-theme="dark"] {
  --color-primary: #ffffff;
  --color-accent: #21a79b;
}

One variable change cascades through every rule that uses it.

Tailwind: Tailwind’s theme config (tailwind.config.ts) compiles to CSS variables. You rarely write var() by hand in a Tailwind project — but you’ll read CSS variables in shadcn/ui components and theme files, and you’ll occasionally override them for theming.

Why this matters in React: Theming, dark mode, brand customization — all CSS variables. Most modern component libraries (shadcn/ui, Radix) ship with a defined variable palette you can override for your capstone’s brand.


Practice exercises

For each, open any web page in Chrome → right-click → Inspect → Elements → edit the Styles pane on the right. Or paste the CSS into a quick style.css file paired with a small index.html.

/* 1. Box-model fix: what property + value makes width
      include padding + border? */
* {
  /* ??? */
}
/* 2. Center a div both vertically and horizontally with flexbox.
      Two properties on the parent: */
.parent {
  display: flex;
  /* ??? */
  /* ??? */
}
/* 3. Three equal columns with Grid — one property to add: */
.cards {
  display: grid;
  /* ??? */
}
/* 4. Tooltip pinned to the top-right corner of its parent.
      What's the position value on each, plus the offset properties? */
.avatar { /* ??? */ }
.badge {
  /* ??? */
  /* ??? */
  /* ??? */
}
/* 5. Stack vertically on mobile, horizontally on desktop (≥768px).
      Fill in the media query: */
.row {
  display: flex;
  flex-direction: column;
}

@media /* ??? */ {
  .row {
    flex-direction: row;
  }
}

Cheat sheet — keep this open while you code

ConceptCSSTailwind
Box-sizingbox-sizing: border-box;(default)
Padding all sidespadding: 16px;p-4
Padding axispadding: 12px 16px;py-3 px-4
Margin centermargin: 0 auto;mx-auto
Borderborder: 1px solid #ccc;border border-gray-300
Display: flexdisplay: flex;flex
Flex directionflex-direction: column;flex-col
Justify contentjustify-content: center;justify-center
Align itemsalign-items: center;items-center
Gapgap: 16px;gap-4
Grid columnsgrid-template-columns: repeat(3, 1fr);grid-cols-3
Responsive gridgrid-template-columns: repeat(auto-fill, minmax(280px, 1fr));(use a plugin / arbitrary)
Position absoluteposition: absolute; top: 0; right: 0;absolute top-0 right-0
Hover.btn:hover { ... }hover:...
Hidedisplay: none;hidden
Media query (md+)@media (min-width: 768px) { ... }md:...
CSS variablevar(--name)bg-[var(--brand)]

What’s next

You’ve now seen the CSS surface you need to read existing styles, write new ones, and understand what every Tailwind utility class actually does under the hood. You’ll write Tailwind classes daily from Week 1 onward — and every one of them maps to a CSS property in this reference.

When you’re ready, post in #wins on Discord: “Module 0.5 complete.” See you in the next module.