Lab 06: CSS-in-JS

Time: 30 minutes | Level: Advanced | Docker: docker run -it --rm node:20-alpine sh

Overview

Compare and implement CSS-in-JS approaches: CSS Modules (compile-time scoping), Vanilla Extract (type-safe zero-runtime), styled-components (runtime), Tailwind CSS (utility-first JIT), and bundle size analysis.


Step 1: CSS Modules — Compile-Time Scoping

CSS Modules transform class names at build time, guaranteeing uniqueness:

/* Button.module.css */
.button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 6px;
  font-size: 0.875rem;
  font-weight: 600;
  cursor: pointer;
  transition: filter 0.15s ease;
}

.button:hover { filter: brightness(1.1); }
.button:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.primary   { background: var(--color-primary); color: white; }
.secondary { background: var(--color-surface-2); color: var(--color-text); }
.danger    { background: var(--color-danger); color: white; }

.small  { padding: 0.25rem 0.75rem; font-size: 0.75rem; }
.large  { padding: 0.75rem 1.5rem; font-size: 1rem; }

/* Composes: inherit styles from another class */
.icon-button {
  composes: button;  /* inherit base button */
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border-radius: 50%;
}

Step 2: Vanilla Extract — Zero-Runtime Type-Safe CSS


Step 3: styled-components — Runtime CSS-in-JS


Step 4: Tailwind CSS — Utility-First


Step 5: Comparison Table


Step 6: Bundle Size Strategies


Step 7: Choosing the Right Approach


Step 8: Capstone — CSS Modules Class Name Hashing

(Create the test file:)

📸 Verified Output:


Summary

Approach
Runtime
Type Safety
Best For

CSS Modules

None

Partial

Component isolation

Vanilla Extract

None

Full TS

Type-safe design systems

styled-components

~14kb

Good

Dynamic themes

Tailwind JIT

None

Partial

Rapid development

CSS custom props

None

None

Universal theming

Emotion

~11kb

Good

SSR + dynamic

Last updated