前言
其实去年就见过 Windi CSS,只是粗浅的了解过,知道 ”Windi CSS 是下一代工具优先的 CSS 框架“(官网的描述),也没有去深入了解实践过。
最近闲下来了也花点时间去研究了一下,确实也是一次全新的体验,短短一行代码就可以囊括大多数的 css 样式,使用起来确实方便。
相较于习惯了写 less 和 sass 的我来说,还是会有一些学习成本在里头,虽然我们公司的项目中也会有一个全局的 scss 文件定义一些常用的工具类,但种类毕竟也有限,今后的项目中也可以考虑是否可以选择使用 Windi CSS 来替代了。
Windi CSS 介绍
下面是 官网 的一段描述,简而言之就是,windicss 是以 Tailwindcss 为灵感制作的库,并且兼容了 Tailwindcss、提供了更快的加载时间和热更新。
对我们而言,windicss 就相当于一个可以让我们快速上手组件库,内置了诸如 flex、items-center、ml-8、bg-purple-600 等 工具类,可以让我们不用再去写那些繁琐的 css 样式,而且只有我们使用的工具类才会产生相对应的 css;不仅如此,windicss 还提供了其他更加强大的功能供我们使用,接下来就去体验一下吧。
Windi CSS 使用
安装配置
我在此使用 vite2 + vue3 来体验 Windi CSS
-
首先安装依赖
pnpm i -D vite-plugin-windicss windicss -
在
vite.config.ts配置文件中添加插件import WindiCSS from 'vite-plugin-windicss' export default { plugins: [ WindiCSS(), ], } -
然后在入口文件
main.ts中导入样式import "virtual:windi.css"; -
最后新建 Windi CSS 的配置文件
windi.config.tsimport { defineConfig } from 'windicss/helpers' export default defineConfig({ /* 配置项... */ })默认情况下,Windi CSS 会在你的项目根目录下搜索配置文件。以下是有效的名称:
windi.config.tswindi.config.jstailwind.config.tstailwind.config.js
基本使用
简单使用 Windi CSS 的工具类,比较一下与正常的使用 sass 之间的区别,还是很明显的,具体的工具类可以参考 官网 。
<template>
<div>
<h3>使用 Windi CSS</h3>
<div class="flex items-center justify-around bg-teal-100 rounded-md p-4px w-192px">
<div class="w-[25%] h-12 bg-red-400 rounded-md m-4px"></div>
<div class="w-[25%] h-12 bg-green-400 rounded-md m-4px"></div>
<div class="w-[25%] h-12 bg-blue-400 rounded-md m-4px"></div>
</div>
<br>
<h3>使用正常的 sass</h3>
<div class="card">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</template>
<style lang="scss" scoped>
.card {
width: 200px;
display: flex;
justify-content: space-around;
align-items: center;
padding: 4px;
border-radius: 6px;
background-color: rgb(204, 251, 241);
.box {
width: 48px;
height: 48px;
margin: 4px;
border-radius: 6px;
}
.box:nth-child(1) {
background-color: rgb(248, 113, 113);
}
.box:nth-child(2) {
background-color: rgb(52, 211, 153);
}
.box:nth-child(3) {
background-color: rgb(96, 165, 250);
}
}
</style>
自动值推导
上述代码可以看到 Windi CSS 提供自动值推导功能,可以在类名中使用任意值,然后生成相应的样式,用起来比使用标准的 sass 要方便很多。例如:
w-192px可以自动解析为width: 192px;w-[25%]可以自动解析为width: 25%;,也相当于width: 48px;h-12可以自动解析为height: 3rem;,根据当前的根元素的字体大小也相当于height: 48px;
Important 前缀
在 Windi CSS 中使用 important 也是非常方便,只需在任意工具类的前面使用 ! 前缀,使它们变为 !important,就可以覆盖之前的样式规则中指定的属性了。
比如给 w-192px 添加 ! 前缀为 !w-192px
<h3>使用 Windi CSS</h3>
<div class="flex items-center justify-around bg-teal-100 rounded-md p-4px !w-192px">
<div class="w-[25%] h-12 bg-red-400 rounded-md m-4px"></div>
<div class="w-[25%] h-12 bg-green-400 rounded-md m-4px"></div>
<div class="w-[25%] h-12 bg-blue-400 rounded-md m-4px"></div>
</div>
Shortcuts
当我们经常使用相同的工具类合集时,会出现很多重复性的代码,Windi CSS 提供了 Shortcuts 特性可以工具类的名字组合在一起定义成一个新的名字,在任何地方使用,就免去了大量重复冗余的代码。
在 Windi CSS 的配置文件 windi.config.ts 中添加 shortcuts 字段:
export default {
theme: {
/* ... */
},
shortcuts: {
'box view': 'w-[25%] h-12 rounded-md m-4px',
},
}
就可以把页面代码修改为下面这样,页面展示效果是一样的,但是代码更加简洁明了。
<h3>使用 Windi CSS</h3>
<div class="flex items-center justify-around bg-teal-100 rounded-md p-4px w-192px">
<div class="bg-red-400 box-view"></div>
<div class="bg-green-400 box-view"></div>
<div class="bg-blue-400 box-view"></div>
</div>
响应式设计
在 Windi CSS 中也可以很轻松实现响应式设计。只需要将可变修饰(variant)的前缀加到对应的工具类前,比如 md:、lg:。
断点
默认 带有 <前缀带有 @前缀sm (min-width: 640px) (max-width: 639.9px) (min-width: 640px) and (max-width: 767.9px) md (min-width: 768px) (max-width: 767.9px) (min-width: 768px) and (max-width: 1023.9px) lg (min-width: 1024px) (max-width: 1023.9px) (min-width: 1024px) and (max-width: 1279.9px) xl (min-width: 1280px) (max-width: 1279.9px) (min-width: 1280px) and (max-width: 1535.9px) 2xl (min-width: 1536px) (max-width: 1535.9px) (min-width: 1536px)
<h3>使用 Windi CSS</h3>
<div class="flex items-center justify-around bg-teal-100 rounded-md p-4px !w-192px">
<div class="lg:bg-red-400 md:bg-red-200 sm:bg-red-100 box-view"></div>
<div class="bg-green-400 box-view"></div>
<div class="bg-blue-400 box-view"></div>
</div>
在不同的断点下,效果如下:
不仅如此,你也可以根据业务需求来自定义断点,在 windi.config.ts 中配置,如命名为 tablet、laptop……
import { defineConfig } from 'windicss/helpers'
export default defineConfig({
theme: {
screens: {
tablet: '640px',
laptop: '1024px',
desktop: '1280px',
},
},
})
指令
Windi CSS 还提供了五个指令,可以配合 CSS 让我们更好的使用。
@apply
可以将 @apply 在 style 块中同一行的、一些已存在的工具类上使用,和 Shortcuts 的效果差不多,很适合抽取成一个通用工具类。
<template>
<div>
<!-- 使用 Windi CSS-->
<h3>使用 Windi CSS</h3>
<div class="flex items-center justify-around bg-teal-100 rounded-md p-4px w-192px">
<div class="bg-red-400 box-view2"></div>
<div class="bg-green-400 box-view2"></div>
<div class="bg-blue-400 box-view2"></div>
</div>
<br>
...
</template>
<style lang="scss" scoped>
...
.box-view2 {
@apply w-[25%] h-12 rounded-md m-4px;
}
</style>
@variants
我们也可以通过把 css 工具类定义包装在 @variants 中,用来生成带有一些屏幕可变修饰,状态可变修饰,主题可变修饰的工具类。
<template>
<div>
<!-- 使用 Windi CSS-->
<h3>使用 Windi CSS</h3>
<div class="flex items-center justify-around bg-teal-100 rounded-md p-4px w-192px">
<div class="bg-red-400 box-view2"></div>
<div class="bg-green-400 box-view2"></div>
<div class="bg-blue-400 box-view2"></div>
</div>
<br>
...
</template>
<style lang="scss" scoped>
...
.box-view2 {
@apply w-[25%] h-12 rounded-md m-4px;
}
@variants focus, hover {
.box-view2 {
@apply bg-red-200;
}
}
</style>
@screen
@screen 指令可以让我们来媒体查询,通过名称来引用断点,以此来取代通过复制你 CSS 里面的值来实现。
<style lang="scss" scoped>
...
.box-view2 {
@apply w-[25%] h-12 rounded-md m-4px;
}
// lg 就是上文响应式设计中的断点 (min-width: 1024px)
@screen lg {
.box-view2 {
@apply bg-red-200;
}
}
// 上下效果一样
@media (min-width: 1024px) {
.box-view2{
// background-color: rgba(254, 202, 202) = bg-red-200
background-color: rgba(254, 202, 202)
}
}
</style>
@layer
@layer 指令用来确认每个 class 的排序。合法的层级为 基础 (base), 组件 (components) 和 工具类 (utilities)。
这个指令我也没用过多地去使用,有兴趣可以自己去研究研究,暂贴一段 官方 提供的代码:
theme()
theme() 函数可以让我们通过 . 运算符来获取想要设置的值。
<template>
<div>
<!-- 使用 Windi CSS-->
<h3>使用 Windi CSS</h3>
<div class="flex items-center justify-around bg-teal-100 rounded-md p-4px w-192px">
<div class="bg-red-400 box-view2 light-red"></div>
<div class="bg-green-400 box-view2"></div>
<div class="bg-blue-400 box-view2"></div>
</div>
<br>
...
</template>
<style lang="scss" scoped>
...
.box-view2 {
@apply w-[25%] h-12 rounded-md m-4px;
}
.light-red {
background-color: theme("colors.red.200");
}
</style>
属性化模式
属性化在 Windi CSS 中 默认情况下是可选的,可以在你的 windi.config.ts 配置中开启,并根据需要来使用。
import { defineConfig } from 'windicss/helpers'
export default defineConfig({
attributify: true,
})
就可以把我们上面的代码改为下面的方式,效果和上面讲到的响应式设计是一样的,但是这样写可以让我们的目录更加清晰。
<h3>使用 Windi CSS</h3>
<div class="flex items-center justify-around bg-teal-100 rounded-md p-4px w-192px">
<div
lg="bg-red-400 box-view"
md="bg-red-200 box-view"
sm="bg-red-100 box-view"
></div>
<div class="bg-green-400 box-view"></div>
<div class="bg-blue-400 box-view"></div>
</div>
如果担心命名冲突,可以在 windi.config.ts 配置中通过属性化方式添加自定义前缀:
import { defineConfig } from 'windicss/helpers'
export default defineConfig({
attributify: {
prefix: 'w:',
},
})
<h3>使用 Windi CSS</h3>
<div class="flex items-center justify-around bg-teal-100 rounded-md p-4px w-192px">
<div
w:lg="bg-red-400 box-view"
w:md="bg-red-200 box-view"
w:sm="bg-red-100 box-view"
></div>
<div class="bg-green-400 box-view"></div>
<div class="bg-blue-400 box-view"></div>
</div>
同样的,我们也可以根据工具类来分组,也还是很方便的:
Plugin 插件
Windi CSS 的官方以及社区提供了很多 plugin 插件供我们去使用,让我们操作 css 更加方便和高效,而且我们也可以通过 Windi CSS 的接口,来开发自己的插件。
插件同样需要在 Windi CSS 的配置文件 windi.config.ts 中引入即可。
export default {
theme: {
// ...
},
// 引入插件
plugins: [
require('windicss/plugin/typography'),
// ...
],
}
而且插件功能也非常强大,有兴趣也可以自己去摸索一下:
- typography:排版插件
- filters:过滤器插件
- plugin-animations:动画插件
- ……
VS Code 插件
Windi CSS 还为 VS Code 编译器提供了一个叫做 Windi CSS Intellisense 的插件,可以直接在 VS Code 插件商店里找到并安装,配合 VS Code 可以拥有一个更好的 Windi 的开发体验,例如:自动补全、语法高亮、代码折叠和构建等等,就和我们平时写标准 css 一样方便。
- 自动补全:为工具类 (utilities) 和可变修饰 (variants) 提供智能建议。
- 悬停预览:悬停于一个 class name 的上方时可以看到其完整的 CSS。
- 语法高亮:高亮工具类、可变修饰和重要的部分。
- 颜色预览:预览颜色和色谱。
- 代码折叠:折叠超长的 classes 以提高可读性。
- 编译命令:内置编译命令,一键操作。
其他功能
除此之外,Windi CSS 还有很多我没用研究到的功能,也是很强大的。
- 暗色模式:Windi CSS 拥有开箱即用的暗色模式支持,只需要对工具类添加可变修饰前缀
dark:即可 - RTL:Windi CSS 拥有开箱即用的从右到左(RTL)书写方式支持,且无需任何配置,只需要对工具类增加
rtl:可变修饰前缀即 - 可视化分析器:一个为 Windi CSS 提供的可视化分析工具。浏览你所有的工具类 (utilities) 使用情况,综观你的设计系统,识别"糟糕的使用",以及更多!
- ……
Windi CSS 总结
优点
Windi CSS 的写法与传统 css 相比,确实可以让人眼前一亮,它内置了大量的工具类确实可以解决大部分的业务需求,也可以更好的进行 css class 的复用;而且它的内置功能也趋于完善,无论是提供 shortcuts 功能、响应式功能,还是提供了指令和 plugin 插件等,都可以让我们开发起来更加方便。而且很多第三方组件也是提供 Windi CSS 支持的,比如我上一篇文章写的 slidev 等。
简而言之,Windi CSS 就是想做一个通用的可定制化的 css “组件库”,省去了我们前期大量思考如何来完成和写好这个样式的时间成本,同时还可以让我们养成一套良好的开发和 UI 规范。
缺点
当然可能也不算是缺点,谨代表我个人的观点。
大量的工具类和功能也会增加短期的学习成本,以及基于你的项目继续开发的阅读成本,在多人协作维护的项目上确实增加一些团队负担。同时页面中很多 class 中使用的大量的工具类,也会大大降低代码的优雅性,造成了 html 结构上的一种拥挤感。而且 css 世界本就丰富多彩,很多的样式还需要 css 搭配 js 来使用,仅凭一个 Windi CSS 是否就可以满足我们所有的需求呢;当我们使用 Windi CSS 和第三方组件搭配使用,就一定可以确保没用问题吗。
更早出来的 Tailwind CSS 还处于舆论的风口浪尖,而 Windi CSS 只是被看作是按需供应的 Tailwind 替代方案,所以 Windi CSS 依然需要经得起时间的考验。
写在最后
无论是在项目中继续使用 less / sass,还是使用那些原子样式的 css 框架 Windi CSS / Tailwind CSS,找到一款适合自己适合团队需求的才是最重要的。
如果你也对 Windi CSS 感兴趣的话,也去自己动手操作操作吧,也许会给你带来意想不到的收获呢。