styled-components:用 JS 写 CSS,React 样式这块它干了十年

styled-components 在 GitHub 上已经拿到 41K Star 了。

2016 年出来的,专门解决 React 里写 CSS 的各种别扭。到现在十年了,依然是 React 生态里用得最多的 CSS-in-JS 方案之一。

正文顶部截图

1、 到底解决了什么问题

React 组件化开发有个老毛病:样式怎么管。

写全局 CSS,类名冲突是家常便饭,改个按钮颜色得全局搜一遍生怕漏掉。CSS Modules 解决了作用域问题,但写起来还是要在 JS 和 CSS 文件之间来回跳。BEM 命名法能用,但那一长串类名写多了谁都烦。

styled-components 的思路很直接:把 CSS 直接写在 JS 组件里,每个组件自带样式,自动生成唯一的类名,不用操心命名冲突,不用维护单独的样式文件。

2、 长什么样

用法很直观。用 tagged template literal 定义一个组件,里面写 CSS:

const Button = styled.button`
  background: palevioletred;
  color: white;
  padding: 0.5em 1em;
  border-radius: 4px;
`;

这个 Button 就是一个带样式的 React 组件,直接当 JSX 用就行。

想根据 props 改样式?插个函数进去:

const Button = styled.button`
  background: ${props => props.$primary ? 'palevioletred' : 'white'};
  color: ${props => props.$primary ? 'white' : 'palevioletred'};
`;

传个 $primary 属性,按钮就变色。$ 前缀是 transient prop,不会被传到 DOM 节点上。

还能继承:

const TomatoButton = styled(Button)`
  background: tomato;
  border-color: tomato;
`;

在 Button 基础上改个颜色,新的组件就出来了。

README区域截图

3、 该有的都有

伪类、伪元素、嵌套选择器,直接用 & 引用当前组件的类名:

const Input = styled.input`
  border: 1px solid #ccc;

  &:focus {
    border-color: palevioletred;
    outline: none;
  }

  &::placeholder {
    color: #aaa;
  }
`;

媒体查询、动画关键帧、全局样式,CSS 支持的它基本都支持。

主题系统用 ThemeProvider 包一层,所有子组件通过 props.theme 拿到设计变量:

const theme = { fg: 'palevioletred', bg: 'white' };

<ThemeProvider theme={theme}>
  <Card>内容</Card>
</ThemeProvider>

还有个 createTheme 方法,把设计变量转成 CSS 自定义属性,做亮色/暗色主题切换的时候,类名哈希值保持稳定,不会出现 hydration 不匹配的问题。

4、 实际用起来怎么样

体积小,gzip 之后不到 13kB,不用装额外的构建插件。

TypeScript 类型是内置的,不用单独装 @types,props 能直接推导到样式里。

服务端渲染、React Server Components、流式 SSR、React Native,一套 API 全覆盖。运行时自动检测环境,不用手动配置。

css helper 可以把公共样式块提出来复用:

const truncate = css`
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
`;

const Label = styled.span`
  ${truncate}
  max-width: 200px;
`;

as prop 可以在不改样式的情况下换掉渲染的 HTML 元素。attrs 可以给组件设置默认的 HTML 属性。

5、 谁在用

只要你的项目用 React,就需要管样式。styled-components 适合这些场景:

  • 组件库开发,需要严格隔离样式作用域
  • 需要主题切换的产品,比如暗色模式
  • 用 Next.js 做 SSR 的项目,需要和 RSC 兼容
  • React Native 项目,想用同一套写法管 Web 和移动端的样式

十年了,API 稳定,社区成熟,遇到问题基本都能搜到答案。

需要主题切换的产品,比如暗色模式

  • 用 Next.js 做 SSR 的项目,需要和 RSC 兼容
  • React Native 项目,想用同一套写法管 Web 和移动端的样式

十年了,API 稳定,社区成熟,遇到问题基本都能搜到答案。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐