Get AI summaries of any video or article — Sign up free
A breakdown of style solutions for 2025 thumbnail

A breakdown of style solutions for 2025

Theo - t3․gg·
5 min read

Based on Theo - t3․gg's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Use a modular mental model: separate CSS extensions, headless behavior primitives, and style layers so updates don’t force full-stack rewrites.

Briefing

Web styling in 2025 is less about finding a single “best” UI toolkit and more about choosing the right mix of modular building blocks—because the all-in-one approach keeps aging badly. The clearest through-line is a three-part mental model: CSS extensions (like Sass, Less, Tailwind), headless/behavior libraries (like Radix UI), and style systems (like Tailwind UI). The practical takeaway is that modern teams get the best long-term results when accessibility and interaction logic come from proven primitives, while visual styling stays swappable and lives closer to the app’s own codebase.

Radix UI sits at the center of that approach. It’s positioned as primitives for complex UI behavior—focus management, accessibility, correct rendering timing, keyboard navigation, and handling web standards—without prescribing how components look. That forces teams to supply theming, either by adopting a theme layer or building their own. Tailwind, meanwhile, is treated as a CSS improvement with design-system ergonomics rather than a fixed visual language. It reduces conflicts by pushing consistent spacing scales and naming conventions, but recent features (like bracket syntax and fractional values) loosen the strictness that once made it feel more “system-like.” The result: Tailwind increasingly behaves like an extension of CSS that helps component architecture, while style-system strictness becomes optional.

The biggest shift in the CSS ecosystem is how styles are produced. Runtime CSS-in-JS—where JavaScript generates styles on the fly—has largely fallen out of favor. Most modern setups generate CSS at build time and only swap class names at runtime. That change undercuts the conspiracy narratives that blame Facebook’s React team for killing CSS-in-JS; the more grounded explanation is engineering tradeoffs and the move toward predictable build-time outputs.

Where the industry’s earlier “middle” solutions went wrong is the promise of doing everything at once. Material UI (MUI) is used as the cautionary example: it bundled component behavior, styling primitives, and a look-and-feel into one package. Over time, those bundled opinions aged unevenly, leaving teams stuck with hacks or forced rewrites when accessibility or API details changed. The same pattern is described as a broader problem with monolithic libraries: when one part breaks, the whole stack must be updated.

That’s why Shadcn UI becomes the centerpiece of the modern recommendation. Instead of locking teams into a single all-in-one system, Shadcn UI assembles a component layer by copying component code into the project (not just installing a black-box dependency). It uses Radix UI and Tailwind as core ingredients, then adds glue like class variance authority for variant-driven styling. Because the component code lives in the app’s repository, teams can restyle it, swap style layers, and update only the granular dependencies that actually change. The maintainability argument is straightforward: updating one dependency (e.g., a Radix-related piece) is less disruptive than auditing an entire monolithic UI framework.

The broader conclusion is that the industry is converging on modularity: treat behaviors, styling, and component composition as separate concerns. The future is framed as brighter because teams can combine best-in-class parts—while still retaining the freedom to own the final look inside their codebase. The remaining caveat is that modularity doesn’t remove responsibility; it makes customization and fixes possible, but teams still need to assemble and maintain their choices.

Cornell Notes

Styling in 2025 is best understood as a modular stack: CSS extensions (e.g., Tailwind), headless behavior primitives (e.g., Radix UI), and style layers (e.g., Tailwind UI). The industry moved away from runtime CSS-in-JS toward build-time CSS generation with class-name swapping, reducing unpredictability. All-in-one component suites like Material UI are criticized for bundling behavior, styling primitives, and appearance into one package that ages unevenly and becomes hard to update without widespread code changes. Shadcn UI is presented as the “middle” solution: it assembles Radix + Tailwind components, then copies component code into the project so teams can restyle and update granular dependencies without being locked into a single monolithic look.

What are the three categories of styling solutions, and why does that classification matter for decision-making?

The framework splits UI styling into (1) CSS extensions—tools that extend how CSS is written (Sass, Less, Tailwind), (2) behavioral/headless libraries—primitives that handle interaction complexity (Radix UI, and previously React Aria), and (3) style systems—opinionated styling layers (Tailwind UI as the example). The key point is that behavior and accessibility are hard to get right, so teams benefit from using battle-tested primitives, while visual styling should remain flexible so it can evolve without forcing a full rewrite.

Why is Radix UI treated as “primitives without theming,” and what work does that shift to the app?

Radix UI provides the hard parts of UI behavior: focus control, accessibility, correct rendering timing, keyboard navigation, and standards handling. It does not fully prescribe how components look—buttons, dropdowns, dialogs, etc. therefore require a theming layer. Teams either pull in Radix themes or solve theming themselves, which keeps behavior and appearance decoupled.

How does Tailwind’s evolution change its role from “strict system” to “CSS improvement,” and what’s the tradeoff?

Tailwind originally felt more system-like because it enforced consistent spacing scales (e.g., only certain padding values). Bracket syntax and fractional values loosen those constraints, allowing inline custom values and making the system less strict. The tradeoff is flexibility versus the loss of the earlier guardrails that made it feel like a tightly controlled design system.

What’s the practical difference between monolithic UI frameworks (like MUI) and modular component layers (like Shadcn UI)?

Monolithic frameworks bundle behavior, styling primitives, and appearance. When updates land—especially accessibility fixes—teams may need to audit and patch many parts because the bundled opinions interact. Shadcn UI instead copies component code into the project and relies on granular dependencies (Radix pieces, Tailwind, class variance authority). That means teams can restyle locally and update only the specific dependency that changed.

Why does the transcript claim CSS-in-JS is effectively “dead,” and what pattern replaced it?

The claim is that modern setups largely stop generating styles at runtime. Instead, styles are generated into a CSS file at build time, and runtime work is limited to swapping class names on elements. That reduces runtime unpredictability and undermines arguments that runtime CSS-in-JS is still the dominant or best path.

How does Shadcn UI avoid “lock-in,” and what does the CLI/component-copy workflow enable?

Shadcn UI doesn’t just install a black-box package; it copies component files into the codebase (e.g., into /source/components) and installs needed dependencies. Because the code is now owned by the app, teams can modify styles directly, swap style layers, and even use alternative component variants (via the CLI) without being trapped by a single upstream design system.

Review Questions

  1. What responsibilities should be assigned to headless behavior primitives versus style systems in a modular UI stack?
  2. How does build-time CSS generation with class-name swapping change the maintenance profile compared with runtime CSS-in-JS?
  3. Why does copying component code into the app’s repository reduce the blast radius of UI library updates?

Key Points

  1. 1

    Use a modular mental model: separate CSS extensions, headless behavior primitives, and style layers so updates don’t force full-stack rewrites.

  2. 2

    Treat Radix UI as behavior/accessibility primitives without built-in theming, and plan for theming as a separate decision.

  3. 3

    Tailwind functions as a CSS improvement and component-architecture tool; newer syntax increases flexibility but reduces strictness.

  4. 4

    Prefer build-time CSS generation over runtime style generation to keep runtime behavior predictable and maintenance simpler.

  5. 5

    Avoid all-in-one UI frameworks when possible because bundled behavior, styling, and appearance tend to age unevenly and complicate upgrades.

  6. 6

    Shadcn UI’s “copy into your repo” approach enables restyling and granular dependency updates without lock-in.

  7. 7

    Modularity shifts responsibility to the app team: flexibility increases, but teams must still assemble and maintain the stack.

Highlights

Radix UI is framed as the accessibility-and-interaction layer: it handles focus, keyboard navigation, and rendering timing, but leaves the visual look to you.
Tailwind’s bracket syntax and fractional values loosen earlier design-system strictness, pushing it more toward “better CSS” than a rigid style system.
The maintenance advantage of Shadcn UI comes from owning component code in the repository, so only granular dependencies need updating.
The industry’s move away from runtime CSS-in-JS is described as a shift to build-time CSS with runtime class-name swapping.
Monolithic UI suites like MUI are criticized for bundling too many concerns, making upgrades and accessibility fixes more disruptive.

Topics

  • UI Libraries
  • Tailwind
  • Radix UI
  • Shadcn UI
  • CSS-in-JS

Mentioned