Frontend Development 11 min read

Understanding CSS, UI, and Style Systems: Tailwind, Styled-Components, and Behavior Libraries

This article explores how modern frontend development separates UI into CSS extensions, behavior libraries, and style systems, compares Tailwind with Bootstrap, discusses the advantages of styled‑components and behavior‑only libraries like Radix‑UI, and offers guidance on building a custom component library with a personal style system.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Understanding CSS, UI, and Style Systems: Tailwind, Styled-Components, and Behavior Libraries

If you are comfortable with English, you can watch the video "CSS in 2023 - Tailwind vs MUI vs Bootstrap vs Chakra vs..." for a visual overview.

Initially I assumed Headless UI was a familiar concept, but feedback showed many still misunderstand it, even questioning whether a component library without styles exists. Therefore I decided to write another article discussing CSS , UI , and UI Library .

style system

The diagram above shows that the UI we build consists of three parts:

CSS ++

Behavior Libraries

Style System

For example, antd is composed of its behavior library react-component and the design specification Antd Design . When we use antd to build a UI, we usually add our own style extensions, merging the three layers into a final UI.

This works fine for pure business needs, but many projects also require strong personalization and differentiation.

Component libraries that bundle a style system —such as MUI or antd —are not ideal when you need full control over the style system, because you are confined to the styles they provide.

Often the desired personalization is a completely custom style system , not something you fetch from npm .

don't npm install your style system, your website deserves better

Tailwind

Tailwind is a very popular CSS framework that offers a rich set of utility classes, enabling rapid construction of desired styles. A common misconception is that Tailwind is just a prettier Bootstrap .

Tailwind isn’t just a nicer Bootstrap , right?

Unlike Bootstrap, which belongs to the style system category, Tailwind is merely a CSS extension that makes writing CSS faster. Its counterpart is usually Sass or less .

Tailwind’s popularity abroad versus its modest adoption in China can be explained by two reasons: (1) building websites overseas is extremely low‑friction, reducing the need for heavy‑duty component libraries; (2) many developers are accustomed to component libraries like antd that embed a style system , making the transition to Tailwind feel uncomfortable.

For instance, antd components such as Tree , Select , TreeSelect , Cascader , Menu , Dropdown , and Anchor expect data, options, or items as props rather than children . This makes it hard to use Tailwind’s utility classes for quick styling.

styled-components

When building component libraries, CSS In JS is a solid choice, and styled-components makes it easy to solve the problems mentioned earlier.

import styled from 'styled-components'
import {Select} from 'antd'

const StyledSelect = styled(Select)`
  .ant-select-selector {
    // write your style
  }
`

Using styled-components , you can quickly override styles and even pass props to change styles dynamically, which is very useful when building a component library.

import styled, {css} from 'styled-components'

const Button = styled.a<{ $primary?: boolean }>`
  --accent-color: white;
  &>button {
    background-color: ${props => props.$primary ? 'var(--accent-color)' : css`...`};
  }
  &:hover {
    filter: brightness(0.85);
  }
`

The only drawback is that styled-components is not as free‑form as Tailwind; you often end up writing the same CSS rules repeatedly.

display:flex;
justify-content:center;
align-items:center;

To reduce duplication, you might create a shared component like:

const FlexCenter = styled.div`
  display:flex;
  justify-content:center;
  align-items:center;
`

While this reduces CSS bundle size for a component library, it adds mental overhead for business developers who just want to write the styles they need without extracting reusable styled-components . This is a key reason why Tailwind’s utility‑first approach has become so popular.

Behavior Libraries

After discussing CSS ++ , let’s talk about Behavior Libraries .

Using Radix‑UI as an example, behavior libraries provide behavior without imposing a style system, unlike component libraries such as MUI . They are typically lightweight, highly accessible, and can be applied to any component.

For example, the Popover component’s accessibility features are shown below, and its trigger is implemented with asChild :

// index.jsx
import * as Popover from '@radix-ui/react-popover';
import './styles.css';

export default () => (
…
…
);

The asChild prop makes the children of Popover.Trigger act as the trigger, allowing the popover to be attached to any component.

Choosing a Stack for Building a Component Library

From the discussion above, my preference for building a custom component library is clear: you should own a style system rather than rely on an npm install ed one. This is why Tailwind UI can be commercialized successfully—many find creating a style system difficult, but Tailwind UI provides the source code for immediate use.

If you need deeper personalization, combine a solid behavior library (e.g., Radix‑UI) with Tailwind or styled-components to craft your own style system , resulting in a truly unique component library.

frontendUICSSstyled-componentstailwindBehavior Libraries
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.