codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
Notes›frontend

Tailwind CSS and Styling

Published 2026-04-28· Updated 2026-05-18·0 views

Tailwind CSS and the Styling Branches

Tailwind CSS is the flagship of the so-called utility-first approach to styling.

1. About Tailwind

Tailwind CSS is an open-source CSS framework started by Adam Wathan. The 0.x alpha was released in November 2017, and 1.0 came out in May 2019. The license is MIT, and the company is Tailwind Labs.

Version When Event
1.0 2019-05 First stable release.
2.0 2020 dark mode, new color palette.
3.0 2021 JIT (just-in-time) engine becomes default.
4.0 2025-01 Rewritten with the Oxide engine (Rust). CSS-based configuration.

4.0 is a major change. Configuration moved from a JS object in tailwind.config.js to a CSS file's @theme block, and the build is now handled by Oxide, rewritten in Rust.

2. utility-first

Tailwind builds UI by composing small, single-purpose classes. Instead of writing new CSS files, classes are attached to markup.

<button class="px-4 py-2 rounded bg-blue-600 text-white hover:bg-blue-700">
  저장
</button>

The justification for this approach is laid out in Adam Wathan's 2017 article "CSS Utility Classes and 'Separation of Concerns'." The point is the observation that "the rationale of separating HTML and CSS actually produces two strongly coupled files."

3. JIT / Oxide engine

JIT, introduced in 3.0, generates CSS only for the classes used. The resulting CSS is small, and arbitrary values (w-[37px]) become possible. Oxide in 4.0 was announced as a Rust rewrite of JIT that improves build speed and memory.

Scan targets are declared with the @source directive in 4.0.

@import "tailwindcss";
@source "./src/**/*.{ts,tsx}";

@theme {
  --color-brand: oklch(0.7 0.14 250);
  --font-display: "Pretendard", sans-serif;
}

4. Relationship to design tokens

Tailwind's configuration is effectively a collection of design tokens (color, spacing, font size, radius, shadow). From 4.0, these tokens are exposed directly as CSS variables, making them easier to share with other tools.

5. Other styling branches

Traditional branches:

Approach Year Notes
Plain CSS 1996 Standard. The weight of cascade and specificity.
Sass / SCSS 2006 Variables, nesting, mixins. Preprocessor.
Less 2009 Similar to Sass. Used until Bootstrap 3.
CSS Modules 2015~ File-scoped. Build-time class hashing.
BEM naming convention 2009~ Solves scope through naming.

CSS-in-JS:

Library Released Notes
styled-components 2016 tagged template literal. Runtime style injection.
Emotion 2017 Similar to styled-components but lighter.
vanilla-extract 2021, Seek Build-time CSS-in-TS. Zero runtime.
Linaria 2018 Build-time extraction.

CSS-in-JS is widely reported to struggle with RSC compatibility. The runtime style injection model does not work naturally inside server components.

6. shadcn/ui and Radix

Tool Notes
Tailwind CSS The standard for utility.
UnoCSS A compatible engine in the Vue ecosystem.
Bootstrap A different model centered on component classes (btn-primary, etc.).
shadcn/ui A model that copies component source code into the project. Combination of Radix UI + Tailwind.
Radix UI Headless accessible components (WAI-ARIA). No styles.

shadcn/ui (2023, shadcn) is closer to a component catalog than an npm library. The CLI copies component files into the user's repository, and afterwards the user owns that code directly. One reason for fast adoption is that it pairs well with Tailwind's utilities.

7. Tailwind 4 install

pnpm add -D tailwindcss @tailwindcss/postcss postcss
/* src/app/globals.css */
@import "tailwindcss";

@theme {
  --color-brand-50:  oklch(0.97 0.02 250);
  --color-brand-500: oklch(0.65 0.15 250);
  --color-brand-900: oklch(0.30 0.10 250);
  --radius-card: 0.75rem;
}

8. clsx + tailwind-merge

A tool that resolves conflicts when classes in the same category (such as p-2 and p-4) collide so that the latter wins.

import clsx from "clsx"
import { twMerge } from "tailwind-merge"

export const cn = (...args: any[]) => twMerge(clsx(args))

<button className={cn("px-2 py-1", primary && "px-4 py-2")} />

9. CVA — variants pattern

import { cva } from "class-variance-authority"

const button = cva("rounded font-medium", {
  variants: {
    intent: { primary: "bg-blue-600 text-white", ghost: "bg-transparent" },
    size: { sm: "px-2 py-1 text-sm", md: "px-4 py-2" },
  },
  defaultVariants: { intent: "primary", size: "md" },
})

<button className={button({ intent: "ghost", size: "sm" })} />

10. Common pitfalls

Overuse of @apply — collecting utilities into a new class diminishes the benefits of utility-first. Keeping class bundles as variables inside a component file is often recommended.

Arbitrary values — w-[37px] is possible, but bypasses design tokens. Frequently used values are best tokenized for consistency.

Dark mode — the default is choosing between class mode (<html class="dark">) and media mode. From 4.0, @variant dark (...) adds more flexibility.

Build-time scan misses — classes in files not covered by @source will not appear in the build output. Dynamically constructed class strings have the same trap.

Spec differences — Tailwind 4 uses modern CSS by default (OKLCH color space, container queries with @container). Verification is needed for environments that must support very old browsers.

Avoiding CSS spec learning — utility does not mean you do not have to learn CSS. Without Flexbox, Grid, and cascade, you cannot compose utilities well either.

Closing thoughts

utility-first feels burdensome at first because of class length. Once it becomes familiar, the freedom of not managing a separate CSS file is significant. Carrying design tokens together also resolves consistency issues.

Next

  • tauri-over-electron
  • i18n-korean-first

We refer to the Tailwind CSS official, Tailwind GitHub, Tailwind 4 announcement, Adam Wathan — Utility Classes, shadcn/ui, Radix UI, vanilla-extract, and Open Props.

More in frontend

All in this category →
  • Dashboard widget uniformity — don''t leave 4 domains with 3 widgets
  • Admin UI — ResourceTable SSOT pattern
  • Page Loading UX
  • Native Integrations — OS Features
  • OCR · STT · TTS
  • SQLite — A Single-File DB for Local Apps