CSS Layer、Tailwind 和 sass 如何共存?

分层理论

Tailwind 提供了一个 Layer 的概念,通过对样式代码进行分层管理,能够有效减少样式冲突的发生。这些样式主要被划分为以下三层:

  1. base:基础层,样式重置
  2. components:组件层,组件和模块的样式。
  3. utilities:工具类层,原子样式(各种实用工具类比如边距、颜色等)

这是一段经典的 tailwind 分层代码:

css 复制代码
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .card {
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  }
}

@layer utils {
  .glow {
    box-shadow: 0 0 10px rgba(0, 0, 255, 0.5);
  }
}

每层的优先级逐层递增。例如,当组件应用了 .card 样式后,可以通过 .glow 在业务代码中轻松覆盖,并且这一过程没有多少思维负担。

这种层级管理的方式在实际项目中相当有用,以前也有过类似的分层理论,比如 ITCSS,但是没有现代前端开发如此完备的基建的基础,使用起来相对复杂,所以难以深入人心。如今只要在项目引用 tailwind,就能方便实践一系列好用的理论,这也可能是 tailwind 能够迅速流行的原因之一。

不少前端应该知道 CSS 也有一个 Layer 的概念。其正式名称是 CSS Cascade Layers。相关的一系列新功能,支持率已经很好了,可以放心使用。

结合原生 CSS

在项目中引用 tailwind 容易引起传染。当子项目使用 tailwind Layer 后,为了主项目也能享受相应的写法加成,主项目也有必要安装并配置 tailwind。对于较大的项目,尤其是有历史积累的代码库,这种"传染性"可能会对架构的统一性与维护性造成负面影响。为了在更大范围的层度保证架构的统一和整洁性,我倾向使用原生 CSS 方法,作为 tailwind 的替代,但不能反过来。反过来 tailwind 只能作为原生 CSS 的补充。

怎么把 tailwind layer 和 CSS Layer 结合起来呢?

CSS Layer 支持在导入时指定层级,所以写法很简单。

css 复制代码
@import "tailwindcss/base" layer(my-base);
@import "tailwindcss/components" layer(my-components);
@import "tailwindcss/utilities" layer(my-utilities);

结合 Sass

但实际能不能这么写取决于你项目中的 postcss 以及相关 CSS 处理器的版本和配置。如果你使用的是 Sass,那至少目前为止得使用另一种写法:

scss 复制代码
@layer app-base {
  @import "tailwindcss/base";
}
@layer app-cmpts {
  @import "tailwindcss/components";
}
@layer app-utils {
  @import "tailwindcss/utilities";
}

使用上述方法可行,但是会在控制台抛警告。

bash 复制代码
Deprecation Warning: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.
More info and automated migrator: https://sass-lang.com/d/import

新版 Dart Sass 将要废 @import语法,详见文档 @import is Deprecated。这个问题大家也应该处理过,直接替换 @use即可。那么惊喜来了,目前为止还是不支持这种 @layer中使 @use @forward之类规则的写法。

scss 复制代码
// ❌ 错误的
@layer app-base {
  @use "tailwindcss/base" as *;
}
@layer app-cmpts {
  @use "tailwindcss/components" as *;
}
@layer app-utils {
  @use "tailwindcss/utilities" as *;
}

因为 Sass 使用的是静态解析,所以在@use需要放到文档头部,而在@layer中使用会打破这个规则。那么有没有解决办法呢?有的,使用内置 API 直接引用 CSS 文件,就能绕过使用@import限制。简单来说就是使用meta.load-cssAPI。

最终代码参考:

scss 复制代码
@use "sass:meta";

@layer base, app-base, components, app-cmpts, cx, utilities, app-utils;
@layer app-base {
  @include meta.load-css("tailwindcss/base");
}
@layer app-cmpts {
  @include meta.load-css("tailwindcss/components");
}
@layer app-utils {
  @include meta.load-css("tailwindcss/utilities");
}

成功跑起来啦,此处应有点赞。

更多

相关推荐
事圆则缓7 小时前
Flutter 状态管理框架对比(一):先看地图,再选工具
前端·javascript·flutter
IMPYLH7 小时前
HTML 的 <tfoot> 元素
前端·javascript·html
鬼手点金7 小时前
Claude Code示范案例-修复 Bug 工作流
java·服务器·前端·javascript·bug·openclaw
paopaokaka_luck8 小时前
个人综合管理小程序(echarts数据看板、健康数据记录与趋势查看、目标拆解和进度管理、日程待办与番茄钟、习惯打卡、收支统计、个人生活记录、跨模块智能提醒)
前端·javascript·spring·小程序·数据分析·echarts·生活
福兮说16 小时前
前端下载大文件,点了按钮半天没反应:fetch + blob 的三个问题和三种替代写法
前端·javascript·性能优化·文件下载
今年下半年18 小时前
【VUE】整合腾讯地图、自定义区域边界、村委名称及资产统计(放大显示资产点位)
前端·javascript·vue.js
可乐鸡翅yeah_21 小时前
hls.js 切换多个视频源,新手开发常见踩坑
开发语言·前端·javascript·ios·ffmpeg·音视频·safari
kyriewen21 小时前
我实测了前端日期的 5 个坑:差 8 小时只是开始
前端·javascript·程序员
anew___21 小时前
《从零手写操作系统 (11):文件系统初探——initrd与VFS抽象层》
java·javascript·算法
今年下半年21 小时前
【VUE3】移动端:使用腾讯地图显示区域统计与放大显示资产点位
javascript·前端框架·vue·地图