原文:https://leerob.io/blog/css
作者:Lee Robinson
译者:ChatGPT 4 Turbo
校对:云谦
编者注:几个收获,1)虽然 2024 的 CSS 已经很强大,但编译步骤还是需要的,比如做语法降级、未使用样式裁剪等,2)流式 CSS 是个新概念,第一次听说,3)作者推荐了 CSS Modules、Tailwind CSS 和 StyleX 三种方案。
2024 年的 CSS 太棒了。
这篇帖子将是我关于 CSS 生态系统以及我目前使用的工具的笔记和想法的集合。
设计约束
用户体验
在访问网站时,加载样式表的极佳体验是什么样的?
- 样式表应尽可能快地加载(文件大小小)
- 样式表除非更改,否则不应重新下载(适当的缓存头)
- 页面内容应该很少布局偏移或没有
- 字体应尽可能快地加载,并最小化布局偏移
开发者体验
我们的工具必须帮助我们创造更好的用户体验。开发者体验虽然重要,但不能凌驾于用户体验之上。
我们使用的样式工具的 DX 如何帮助我们创造更好的 UX?
- 剪除未使用的样式,压缩并压缩 CSS 以减小文件大小
- 生成哈希文件名以实现安全、不可变的缓存²
- 将 CSS 文件打包在一起以减少网络请求
- 避免命名冲突以防止视觉回归(visual regressions)
如何帮助我们编写更易维护、更令人愉快的 CSS?
- 删除相应 UI 代码时容易删除样式
- 易于遵循设计系统或一系列主题
- 编辑器反馈支持 TypeScript,自动完成和代码检查
- 在编辑器中接收工具反馈以防止错误(类型检查,代码审查)
2024 年的 CSS
编写出色的样式从未如此简单,无需任何额外工具。
下面的例子使用了许多最新的跨浏览器支持的 CSS 功能,无需任何构建步骤。你可能不再需要 Sass 或 Less 了!
https://codesandbox.io/s/jyftfw?file=%2Fstyles.css&utm_medium=sandpack
这是否意味着工具不再必要了?对某些人来说,是的。
构建步骤
为了满足上述设计约束,你可能需要一个构建步骤。
不太可能所有用户都使用最新版本的浏览器。但更重要的是,总会有一些新的语法尚未得到跨浏览器的支持,而你会想要使用这些语法。
你可以手动编写 @supports 规则来检查浏览器支持,但这只能解决部分问题。与其让人类来优化 CSS,为什么不让机器来处理呢?
编译
编译器使以下工作流程变得简单:
- 自动删除任何未使用的样式,将文件打包以减少网络请求,添加供应商前缀,并通过删除空白和注释来压缩输出
- 自动生成唯一文件名,允许框架设置像
immutable
这样的缓存头,向浏览器发出内容永不更改的信号 - 指定目标浏览器(browserslist)并通过语法降级来编译现代 CSS 功能,以便与这些浏览器兼容
流式 CSS
你访问 Google 来预订航班。它无法预先计算出你的意图,因此你最初得到的 UI 是一个搜索栏。你搜索 "Flight SFO to NYC"
,服务器会流式传输一个航班小部件以选择日期。
Google 不可能提前包含所有可能的小部件。货币转换、计时器、实时体育比分,应有尽有。这些小部件的 UI 和样式需要动态流式传输。
React(和 Next.js)现在支持带有流式 SSR 和 CSS 的模式。在 React 模型中,你定义了作为组件的 UI,这些组件依赖于样式。我们如何能够安全地为小部件流式传输样式,而不影响页面上的任何内容?
样式需要是作用域限定的,或者是原子化的,这样即使它们比它们要设置样式的 DOM 内容更早加载,也不会改变页面上已有元素的样式。
例如,CSS Modules 有样式规则限定在导入它的组件范围内。Tailwind 使用原子化的工具类,这些类被编译成一个单独的样式表,在任何类被使用之前加载。StyleX 也生成原子类。全局样式与流式传输不太兼容,除非在流的开始就加载。
我的推荐
CSS Modules
CSS Modules 是在普通 CSS 基础上的一个小而有影响力的增强。
他们满足了我们想要的 UX 约束条件,以及大部分(但不是全部)的 DX 约束条件。它们在几乎所有现代打包工具和框架中都可用。你可以复制 / 粘贴现有的 CSS 选择器,它们将在 CSS 模块中无需任何更改即可工作。
它们无法生成原子样式。它们不支持使用多个主题(仅支持 CSS 变量)。而且因为样式代码不在你的 TypeScript 文件中,你无法获得类型安全和自动完成。但这些限制对你来说可能是可以接受的。
💡 Vite 使用支持 CSS Modules 的 Lightning CSS,不久后 Tailwind 和 Next.js 也将使用。像
postcss
和autoprefixer
这样的工具正在被更快的、一体化的 Rust 工具链所取代。
Tailwind CSS
Tailwind 使用编译器生成仅使用的类。因此,虽然实用程序 CSS 框架包含许多可能的类名,但只有使用的类(例如 "font-bold text-2xl"
)会被包含在单个编译后的 CSS 文件中。
假设你只编写 Tailwind 代码,你的打包文件大小将不会超过所使用的 Tailwind 类的总和。你几乎不可能用到它们全部。这意味着生成的 CSS 文件大小有一个固定的上限,然后通过压缩、缩小和缓存来达到最佳性能。
你不必只编写 Tailwind 样式。Tailwind 类只是遵循设计系统的普通 CSS 工具类。例如,你可以将 Tailwind 与 CSS Modules 混合使用。
Tailwind 并非没有权衡。有一系列工具可以与之搭配:
- VSCode 集成用于自动完成、语法检查、语法高亮等功能
- Prettier 集成用于自动排序类名
Tailwind 最有争议的部分是它的语法。它既被喜爱也被讨厌。在我用它构建了一些东西之前,我并不欣赏 Tailwind,所以如果你的初步反应是反感的,我建议尝试一下。
https://codesandbox.io/s/z7gkmc?file=%2Findex.html&utm_medium=sandpack
StyleX
大多数 CSS-in-JS 库存在两个问题:
- 性能: 组件必须将 JS 中编写的样式转换为 CSS,并在渲染时插入到文档中。这可能会带来相当大的成本,这就是为什么库正在向像 StyleX 这样的“零运行时”库转移的原因。
- 兼容性: 许多现有的 CSS-in-JS 库已经增加了对 React 流式服务器渲染的支持,但仍然不兼容其他性能优化,比如将应用程序的部分内容移至 React 服务器组件。
为了解决这些问题,已经创建了像 Vanilla Extract、Panda 等“零运行时”CSS-in-JS 库。
StyleX 是最新的 CSS-in-JS 库,它解决了这些问题以及更多。如果你想深入了解,我建议阅读“Thinking in StyleX”。
这个例子是我第一次使用 StyleX。虽然它对开源来说还很新(生态系统也反映了这一点),但它并不是一个新库。它支持所有 Meta 网站:Facebook、Instagram、WhatsApp 和 Threads。
你仍然需要给事物命名 🫠 输入 buttonWrapperContainer
。
结论
CSS 对我来说现在有趣吗?我想是的。我很期待未来几年会带来什么。
你会选择不同的东西吗?我漏掉了什么吗?请告诉我。
¹: More: linear() easing, subgrid, dynamic viewport units, color spaces, and @layer.
²:由于文件名保证是唯一的,你可以设置 immutable
缓存头,告诉浏览器内容永远不会改变。这允许浏览器永久缓存文件,这对性能来说是非常好的。