文章目录twin.macro在 CSS-in-JS 里写 Tailwind 的小工具1、 解决什么问题2、 怎么用3、 几个值得一提的特性4、 适合谁5、 注意点twin.macro在 CSS-in-JS 里写 Tailwind 的小工具twin.macro 在 GitHub 上拿到了 8,029 Star。它做的事情很直接把 Tailwind 的原子类搬进 CSS-in-JS 体系。你可以在 jsx 元素上加tw属性写 Tailwind 类名Babel 在编译期把这些类名翻译成 CSS 对象再交给 styled-components 或 emotion 处理。运行时没有任何额外代码。1、 解决什么问题Tailwind 和 CSS-in-JS 长期是两条路线。Tailwind 写得快、约束统一但遇到条件样式、组件复用、动态主题时容易写丑styled-components 和 emotion 灵活可 class 名一长串维护成本不低。twin.macro 把两者焊接在一起。类名用 Tailwind 的写法组合和条件逻辑用 CSS-in-JS 的能力。编译期处理掉 Tailwind 类输出干净的 CSS 对象运行时没有 Tailwind 的样式表也没有 JS 运行库负担。2、 怎么用最简的用法import 一下给元素加tw属性import twin.macro const Input () input twborder hover:border-black /需要条件样式用cssprop 配合twimport tw from twin.macro const Input ({ hasHover }) ( input css{[twborder, hasHover twhover:border-black]} / )要建组件也行tw可以构造带样式的组件还能在已有组件上叠加样式import tw from twin.macro const Input tw.inputborder hover:border-black const PurpleInput tw(Input)border-purple-500复杂场景切到styledimport写函数式 props 到样式的映射和 emotion 的 API 保持一致。3、 几个值得一提的特性变体分组。Tailwind 写响应式或伪类时类名会膨胀twin 支持括号分组div twsm:(w-4 mt-3) lg:(w-8 mt-6) / div twhover:(text-black underline) focus:(text-blue-500 underline) /嵌套也可以sm:(bg-black hover:(bg-white w-10))这种写法合法。编译期转换。Babel 跑一遍tw调用被替换成 CSS 对象没有运行时解析。打包体积上不会因为用了 Tailwind 类而带一份 JS 运行库twtext-sm md:text-lg// ↓ ↓ ↓ ↓ ↓ ↓{fontSize:0.875rem,media (min-width: 768px):{fontSize:1.125rem,},}Tailwind 配置自动补全。类名打错了会提示列出配置里接近的候选✕ ml-1.25 was not found Try one of these classes: - ml-1.5 0.375rem - ml-1 0.25rem - ml-10 2.5remVSCode 的 Tailwind 官方插件也能直接对接写tw时有自动补全。theme import。Tailwind config 里的值能在 JS 里直接取themecolors.purple.500方便写在非样式场景里。!important 简写。类名末尾或开头加!就转成 importantdiv twhidden! /等价于display: none !important。多个类一起 important 用括号包(hidden ml-auto)!。4、 适合谁适合已经在用 styled-components 或 emotion又想用 Tailwind 类名写样式的团队。也适合从 Tailwind 起步、但项目需要 CSS-in-js 的运行时能力条件样式、props 驱动、动态主题的开发者。官方维护了一份配套示例仓库覆盖 Vite、Next.js、Webpack、Parcel、CRA、Gatsby、Blitz、Storybook 等主流组合每种栈都有 styled-components 和 emotion 两个分支的 TypeScript 版本。上手基本是 clone 一个示例改不用自己捣腾 Babel 配置。5、 注意点它是 Babel macro依赖编译期处理。用 Vite、Webpack 这类支持 Babel 的构建链路最顺。CRA 已经内置 macro 支持。如果用 SWC 走纯 Rust 转译链路需要额外的babel-plugin-twin插件才能用tw和css属性而不写 import。styled-components 和 emotion 的运行时仍然在twin 解决的是写法问题不是替换 CSS-in-JS 的运行时机制。期待它能让运行时样式完全消失的开发者要注意这点。项目作者提到了它的源头是babel-plugin-tailwind-components那段工作由 Brad Cornes 完成twin.macro 在此基础上做了一层 macro 包装和 API 整理。它的源头是babel-plugin-tailwind-components那段工作由 Brad Cornes 完成twin.macro 在此基础上做了一层 macro 包装和 API 整理。