airi 项目 UnoCSS 实战:用 transformerDirectives 在 CSS 中原生启用 @apply、@screen、theme() 与 icon()

发布时间:2026/9/9 23:45:54

airi 项目 UnoCSS 实战:用 transformerDirectives 在 CSS 中原生启用 @apply、@screen、theme() 与 icon() airi 项目 UnoCSS 实战用 transformerDirectives 在 CSS 中原生启用 apply、screen、theme() 与 icon()【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airitransformerDirectives 是 UnoCSS 提供的一个核心 transformer它让开发者能够直接在 CSS 中书写apply、screen、theme()与icon()四种指令把工具类utilities与主题theme能力搬进普通 CSS 文件中。在 airi 仓库中这条能力既被根配置集中启用uno.config.ts也被应用到桌面端渲染层如 spotlight.vue的复杂渐变与响应式样式编写上。读完本文你将掌握四种指令的完整语法、别名配置方法以及如何像 airi 一样在 Vue SFC 的 scoped style 里优雅地混用工具类与原生 CSS。本文的原始知识卡位于仓库 .agents/skills/unocss/references/transformer-directives.md下面结合 airi 的真实配置与源码逐层展开。transformerDirectives 解决的问题在纯 UnoCSS 工作流中工具类通常直接写在模板的 class 属性中。但当你需要复用一组工具类、或想在::before/::after等伪元素、keyframes内部、媒体查询里组合样式时模板 class 就无能为力了。transformerDirectives 正是为此而生——它扫描 CSS 源码把指令转换为展开后的工具类声明使样式逻辑收敛到 CSS与工具类按需生成两种范式可以共存。安装与最小配置非常简单在 UnoCSS 配置文件通常是uno.config.ts中加入 transformer 即可import { defineConfig, transformerDirectives } from unocss export default defineConfig({ transformers: [ transformerDirectives(), ], })airi 中的启用方式从根配置到各应用共享airi 的根级 uno.config.ts 把共享配置封装为sharedUnoConfig()其中 transformers 同时启用了 directives 与 variant group 两个转换器并对别名做了显式限定// 根 uno.config.ts节选 transformers: [ transformerDirectives({ applyVariable: [--at-apply], }), transformerVariantGroup(), ],这里的关键点显式传入applyVariable: [--at-apply]后自定义属性别名只保留--at-apply一个不再包含默认同义别名详见下文别名一节。随后不同子应用通过mergeConfigs复用这份共享配置——例如 packages/stage-ui/uno.config.ts 直接合并了根配置import { defineConfig, mergeConfigs } from unocss import { histoireUnoConfig, sharedUnoConfig } from ../../uno.config export default mergeConfigs([ sharedUnoConfig(), histoireUnoConfig(), defineConfig({}), ])也有的应用独立声明完整配置例如 apps/component-calling/uno.config.ts 中与transformerVariantGroup()并排启用了默认形态的transformerDirectives()不传参数。仓库通过 pnpm workspace catalog 统一锁定了unocss版本见 pnpm-workspace.yaml 中unocss: 66.7.5的 catalog 条目因此各应用获得的 transformer 行为是一致的。apply在 CSS 中内联工具类基础用法与带变体的写法apply可以把一组工具类合并进任意 CSS 规则中最直接的应用是封装类组件化的样式.custom-btn { apply py-2 px-4 font-semibold rounded-lg; }当需要混入hover:、focus:等**变体variant**时由于变体值中带冒号与空格必须使用引号包裹整个字符串否则指令解析会失败.custom-btn { apply hover:bg-blue-600 focus:ring-2; }CSS 自定义属性替代写法vanilla CSS 兼容apply是标准 CSS 之外的指令语法若希望样式文件仍能通过普通 CSS 解析器例如防止原生 CSS 校验报错或希望渐进增强可改用 CSS 自定义属性别名.custom-div { --at-apply: text-center my-0 font-medium; }transformer 支持三个同义别名配置如下transformerDirectives({ applyVariable: [--at-apply, --uno-apply, --uno], // 或完全关闭别名能力applyVariable: false })默认别名是--at-apply当传入数组时数组内容即生效别名集合设为false可关闭该特性若你的样式表中恰好有用到这些自定义属性的场景可避免误展开。airi 的真实用法伪元素 复杂渐变 深色模式自定义属性写法在 airi 桌面端被大量使用因为它能出现在::before/::after这类伪元素规则中与手写 position、mask-image 等原生属性无缝共存。下面摘自已搜索可见的 apps/stage-tamagotchi/src/renderer/pages/spotlight.vue舞台 spotlight 输入框的光晕层.spotlight-card::before { pointer-events: none; --at-apply: bg-gradient-to-r from-primary-500/25 via-primary-500/12 to-transparent dark:from-primary-400/25 dark:via-primary-400/12 dark:to-transparent; content: ; position: absolute; inset: 0; z-index: 0; width: 85%; height: 100%; mask-image: linear-gradient(120deg, white 100%); } .spotlight-card::after { pointer-events: none; --at-apply: bg-dotted-[primary-300/35] dark:bg-dotted-[primary-200/16]; position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; background-size: 10px 10px; content: ; mask-image: linear-gradient(165deg, white 30%, transparent 55%); }这个例子至少说明了三点实战要点值必须带引号多段工具类含空格与dark:变体必须写成引号字符串--at-apply后的值才会被当作完整指令解析可以消费自定义规则与主题色bg-dotted-[primary-300/35]对应根配置 uno.config.ts 中自定义的bg-dotted-[...]规则而primary-300等色板来自presetChromatic生成的主题——证明--at-apply展开的是与模板 class 完全一致的完整工具类体系原生 CSS 与指令可并存同一规则内mask-image、background-size、position等手写声明与--at-apply互不干扰这让UI 引擎层样式保持为可读的 CSS。另一个更简洁的用法见 apps/stage-tamagotchi/src/renderer/pages/index.vue加载动效墙.wall { --at-apply: text-primary-300; --wall-width: 8px; animation: wall-move 1s linear infinite; background-image: repeating-linear-gradient( 45deg, currentColor, currentColor var(--wall-width), #ff00 var(--wall-width), #ff00 calc(var(--wall-width) * 2) ); }这里--at-apply: text-primary-300仅为元素注入文字颜色随后手写的background-image通过currentColor引用它——指令与原生 CSS 通过颜色关键字协同工作是工具类用于取主题 token、原生 CSS 负责复杂绘制的理想分工。提示从源码检索看airi 的 Vue SFC 中统一采用--at-apply别名而非apply关键字。若团队规约更看重可迁移性可采用与根配置一致的applyVariable显式列表避免样式被其他解析器误读。screen把断点写成语义化的媒体查询screen 断点名会被转换为对应的媒体查询断点名称来自主题breakpointspresetWind3 / preset-mini 默认提供sm/md/lg/xl/2xl等。经典响应式栅格示例.grid { display: grid; grid-template-columns: repeat(2, 1fr); } screen sm { .grid { grid-template-columns: repeat(3, 1fr); } } screen lg { .grid { grid-template-columns: repeat(4, 1fr); } }相比手写媒体查询screen的可读性更强且断点值始终与主题定义保持单一事实来源。断点变体lt- 与 at-除默认的大于等于某断点语义外还支持两种变体/* 小于某断点才生效max-width 语义 */ screen lt-sm { .item { display: none; } } /* 仅在该断点区间生效min/max 组合 */ screen at-md { .item { width: 50%; } }这在移动端隐藏某元素仅中屏横排等场景中比默认的向上兼容语义更精确。theme()在任意 CSS 属性中读取主题令牌theme(路径点分字符串)允许在 CSS 值里直接读取 UnoCSS 主题配置避免把colors.blue.500这类十六进制硬编码散落在样式文件中.btn-blue { background-color: theme(colors.blue.500); padding: theme(spacing.4); border-radius: theme(borderRadius.lg); }取值路径采用点分记号映射到根配置defineConfig({ theme: {...} })的对象结构。airi 根配置扩展了丰富的主题段见 uno.config.ts例如theme.fontFamily中定义的cute/cutejp/sans-rounded等字体族、以及theme.animation下一整套 keyframes / durations / timingFns 的入场退场动画配置——这些都可以通过theme(fontFamily.cute)、theme(animation.durations.fadeIn)这类写法在 CSS 中引用与apply、模板 class 读取的是同一份主题数据。icon()把图标工具类转成 SVG 背景图icon()指令能把预设图标工具类如i-carbon-sun转换为内联 SVGbackground-image。它依赖 preset-icons 提供图标解析——airi 根配置恰好启用了presetIcons并挂载了多个 Iconify 集合见 uno.config.ts.icon-sun { background-image: icon(i-carbon-sun); } /* 第二个参数指定自定义颜色 */ .icon-moon { background-image: icon(i-carbon-moon, #fff); } /* 颜色参数同样支持 theme() 读取主题色 */ .icon-alert { background-image: icon(i-carbon-warning, theme(colors.red.500)); }注意两点颜色的使用方式是覆盖图标原色本质是为内联 SVG 注入指定色值而theme(colors.red.500)之所以用双引号是因为它嵌套在外层单引号之内且颜色参数本身是一个表达式而非普通字符串。该能力非常适合为那些无法通过text-*染色的背景型图标注入主题色。完整组合示例Card 组件把四种指令放进一个组件级样式即可看到它们如何协作完整示例亦保留于原始知识卡.card { apply rounded-lg shadow-md p-4; background-color: theme(colors.white); } .card-header { apply font-bold text-lg border-b; padding-bottom: theme(spacing.2); } screen md { .card { apply flex gap-4; } } .card-icon { background-image: icon(i-carbon-document); apply w-6 h-6; }从这份示例可以归纳协作模式apply负责排版骨架与可见性theme()负责取值screen负责响应式分段icon()负责图形资产。在 airi 这类多端Web / Electron / Capacitor / tamagotchi 桌面应用monorepo 中把这份 CSS 放在公共 UI 包如 packages/stage-ui内配合根配置的分层启用策略即可保证各端获得一致的指令行为。使用建议与注意事项作用域内使用在 Vue SFC 中style scoped内的apply/--at-apply展开发生在 UnoCSS 构建阶段Vue 的 scoped 属性处理与其并不冲突airi 的多个页面即采用这种组合。带空格与变体务必加引号apply与--at-apply的值若包含hover:/dark:/ 空格分隔的多段类名必须整体加引号否则会被当作单一工具类解析失败。别名的统一管理既然项目从根配置统一了applyVariable新增子应用时应优先复用sharedUnoConfig()或与其保持一致避免不同应用间别名集合漂移。图标类需存在集合icon()依赖presetIcons及其配置的 collections如果图标名不在已加载集合内构建期不会生成对应背景图。与 extractor 的配合apply/--at-apply等指令内出现的工具类由 transformer 收集并触发生成airi 根配置的 content pipeline见 uno.config.ts同时覆盖.vue、.ts/.js等文件确保 CSS 中引用的类与模板中用到的类都进入统一扫描范围。若需进一步了解相关的 preset-icons、preset-wind3、variant-group 与 shortcuts 能力可继续查阅仓库 .agents/skills/unocss 下的 references 知识卡如 preset-icons.md、preset-wind3.md、transformer-variant-group.md、core-shortcuts.md它们与本文共同构成 UnoCSS 在 airi 中的完整使用参考。【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/9 23:45:54

一串9引发的技术思考:数值溢出与边界测试

1. 先别急,这个标题到底在说什么我先说结论:这个“项目标题”一共14个9,没有别的字符。你把它丢给我,让我拆解背后的核心领域、技术点、应用场景,那我第一反应是——这根本不是传统意义上的项目名,而是一串…

2026/9/9 23:40:53

乐鑫ESP32模组智能交互实战:选型、语音、GUI与量产避坑指南

1. 乐鑫模组为什么总能出现在智能交互的第一线 做智能硬件这几年,我发现一个很有意思的现象:不管是做智能音箱、中控屏、离线语音开关,还是做雷达人体存在传感器,大家聊着聊着总会提到乐鑫。早些年大家用ESP8266做联网&#xff0c…

2026/9/9 23:40:53

2007年数学建模B题公交车调度优化:从建模到代码实现

简介:2007年全国大学生数学建模B题通常涉及交通网络或公交路径优化,Dijkstra算法是求解最短路径的核心工具。该压缩包提供了当年参赛队伍的完整Java实现,包含7个Java源文件、11个编译后的class文件以及Eclipse工程配置文件,共21个…

2026/9/10 0:36:01

PySide6开发桌面天气应用全攻略:从API对接、界面设计到打包部署

“桌面版天气预报应用”这个名字听起来简单,但真正动手做的时候,你会发现它几乎能逼你把桌面开发、网络请求、数据解析、状态管理、异常处理、打包分发这条路完整走一遍。我最初想做个桌面天气应用,纯粹是因为受够了手机天气推送的过度设计—…

2026/9/10 0:36:01

基于Simulink的光储联合系统虚拟同步机控制与削峰填谷仿真

我们直接进入正题。光伏电站并网,遇到的两个老大难问题:一是并网后系统惯性低,电网一有波动站里就跟着抖;二是发电曲线和负荷曲线对不上,中午猛发、傍晚急跌,俗称"鸭子曲线"。用储能配合虚拟同步…

2026/9/10 0:36:01

C# WinForms医院挂号管理系统开发实战解析

简介:这是一份基于C# WinForm开发的医院挂号管理系统项目,采用C/S架构与MVC分层设计,覆盖用户管理、科室管理、医生管理以及门急诊挂号、挂号查询、修改口令、挂号单打印和帮助文档等核心模块,适合正在学习C#桌面应用或医疗管理系…

2026/9/10 0:36:01

用Triton手写21个Kernel,Qwen3.5推理提速至223 tokens/s

我花了两周时间,用 Triton 手写了 21 个 kernel,把 Qwen3.5-0.8B 的完整推理链路从 PyTorch 的自动调度里一层层剥出来,最终在单张消费级显卡上把生成速度压到了 223 tokens/s。整个过程远没有标题看起来那么光鲜,中途遇到过 NaN …

2026/9/9 13:11:35

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 7:15:15

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/10 0:00:55

目录对比去重实战:用哈希算法精准清理重复文件

我电脑里现在还有一块换了三次机的“数据墓地”硬盘,里面存着2016年以前所有旧笔记本的完整备份。平时不觉得有什么,直到前阵子想把它整理归档,发现同一个安装包、同一批照片、同一份论文草稿,在几个不同的备份目录里反复出现。更…

2026/9/10 0:00:55

Leaflet离线地图完整Demo合集:内网部署与坐标纠偏实战

简介:这是一份面向Web GIS开发者的LeafLet离线地图示例合集,帮助开发者快速掌握离线地图从搭建到交互的完整流程。压缩包共723个文件,大小14.06MB,以319个js脚本、175个html页面和29个css样式文件为主体,配合png/svg图…

2026/9/10 0:00:55

MATLAB读取Rinex 3.02观测文件:多系统GNSS数据解析实战

简介:基于MATLAB开发的Rinex3.02版观测文件(o文件)读取代码包,面向卫星定位导航方向的学习者与研究人员,用于解决新版观测文件的数据解析、历元提取与时间转换问题。压缩包共4个文件,包含两个m脚本、一个19…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/7 22:46:00

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/9 10:21:54

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码