样式方案的意义
对于初学者来说,谈到开发前端的样式,首先想到的就是原生CSS。但是时间一长,难免会发现原生CSS开发的各种问题。那么,如果我们不使用任何CSS工程方案,又会出现哪些问题呢?
- 开发体验不好,比如原生的CSS不支持浏览器的嵌套:
// 选择器只能平铺,不能嵌套
.container .header .nav .title .text {
color: blue;
}
.container .header .nav .box {
color: blue;
border: 1px solid grey;
}
- 样式污染问题。如果出现同样的类名,很容易造成不同的样式污染和覆盖。
// a.css
.container {
color: red;
}
// b.css
// 很有可能覆盖 a.css 的样式!
.container {
color: blue;
}
-
浏览器兼容问题。为了兼容不同的浏览器,我们需要对一些属性(如transition)加上不同的浏览器前缀。比如-webkit-、-moz-、-ms-、-o-,意味着开发一个样式我们要写很多代码。
-
打包后的代码体积的问题,如果不适用任何的CSS工程方案,所有的CSS代码都将被打包到产物中。即使有部分样式并没有在代码中进行使用。导致产物体积过大。
针对以上原生CSS的痛点,社区中诞生了不少的解决方案,常见的有5类。
- CSS预处理器:主流的包括
SASS/Scss.less和stylus。这些方案各自定义了一套语法,让CSS也能够使用嵌套规则,甚至能够像编程语言一样定义变量、写条件判断和循环语句。大大增加了样式语言的灵活性,解决原生CSS开发的体验问题。 - CSS Modules:能够将CSS类名处理成hash值,这样就可以避免同名的情况下的样式污染问题。
- CSS 后处理器PostCSS:用来解析和处理CSS代码。可以实现的功能非常的丰富,比如将px转换成rem。根据目标浏览器的情况自动加上类似于--moz--,-o-的属性前缀等。
- CSS in JS方案,主流的包括emotion、styled-components等等。顾名思义,这类方案可以实现直接在CSS中写样式代码。基本包含CSS预处理器和CSS Modules的各项优点,非常的灵活,解决了开发体验和全局样式污染的问题。
- CSS原子化框架,比如TailwindCSS、Windi CSS,通过类名来指定样式。大大简化了样式写法。提高了样式开发的效率。主要解决了原生CSS开发体验的问题。
Vite配置tailwindCSS
安装依赖
pnpm install -D tailwindcss postcss autoprefixer
新建两个配置文件:
// tailwind.config.cjs
module.exports = {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
// postcss.config.cjs
// 从中你可以看到,Tailwind CSS 的编译能力是通过 PostCSS 插件实现的
// 而 Vite 本身内置了 PostCSS,因此可以通过 PostCSS 配置接入 Tailwind CSS
// 注意: Vite 配置文件中如果有 PostCSS 配置的情况下会覆盖掉 post.config.js 的内容!
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
在项目的入口CSS文件中添加代码
@tailwind base;
@tailwind components;
@tailwind utilities;
修改APP.jsx文件
<h1 className='bg-red-400'>Vite + React</h1>
效果:
Vite项目配置CSS预处理器
Vite 本身对 CSS 各种预处理器语言(Sass/Scss、Less和Stylus)做了内置支持。也就是说,即使你不经过任何的配置也可以直接使用各种 CSS 预处理器。我们以 Sass/Scss 为例,来具体感受一下 Vite 的零配置给我们带来的便利。
由于 Vite 底层会调用 CSS 预处理器的官方库进行编译,而 Vite 为了实现按需加载,并没有内置这些工具库,而是让用户根据需要安装。因此,我们首先安装 Sass 的官方库,安装命令如下:
pnpm i sass -D
安装好了之后,我们就可以直接用了
Sass配置全局变量
- 新建一个文件,命名为variable.scss文件。然后在vite.config.ts中进行如下修改
// vite.config.ts
import { normalizePath } from 'vite';
// 如果类型报错,需要安装 @types/node: pnpm i @types/node -D
import path from 'path';
// 全局 scss 文件的路径
// 用 normalizePath 解决 window 下的路径问题
const variablePath = normalizePath(path.resolve('./src/variable.scss'));
export default defineConfig({
// css 相关的配置
css: {
preprocessorOptions: {
scss: {
// additionalData 的内容会在每个 scss 文件的开头自动注入
additionalData: `@import "${variablePath}";`
}
}
}
})
这样你就可以使用scss的全局变量了。相比手动引入方便很多
Vite配置CSS Module
CSS Modules 在 Vite 也是一个开箱即用的能力,Vite 会对后缀带有.module的样式文件自动应用 CSS Modules。接下来我们通过一个简单的例子来使用这个功能。
假设我们有一个scss文件为index.scss,现在我们将其命名为index.module.scss。然后我们修改下tsx中的文件的内容。
// index.tsx
import styles from './index.module.scss';
export function Header() {
return <p className={styles.header}>This is Header</p>
};
可以看到,我们的CSS样式就已经生效了。p标签的类名就被处理成了哈希值的形式。
我们可以在配置文件中的css.modules选项来配置CSS Modules的功能。
// vite.config.ts
export default {
css: {
modules: {
// 一般我们可以通过 generateScopedName 属性来对生成的类名进行自定义
// 其中,name 表示当前文件名,local 表示类名
generateScopedName: "[name]__[local]___[hash:base64:5]"
},
preprocessorOptions: {
// 省略预处理器配置
}
}
}
Vite配置PostCSS多浏览器适配方案
一般你可以通过 postcss.config.js 来配置 postcss ,不过在 Vite 配置文件中已经提供了 PostCSS 的配置入口,我们可以直接在 Vite 配置文件中进行操作。
首先,我们来安装一个常用的 PostCSS 插件——autoprefixer:
pnpm i autoprefixer -D
这个插件主要用来自动为不同的目标浏览器添加样式前缀,解决的是浏览器兼容性的问题。接下来让我们在 Vite 中接入这个插件:
// vite.config.ts 增加如下的配置
import autoprefixer from 'autoprefixer';
export default {
css: {
// 进行 PostCSS 配置
postcss: {
plugins: [
autoprefixer({
// 指定目标浏览器
overrideBrowserslist: ['Chrome > 40', 'ff > 31', 'ie 11']
})
]
}
}
}
配置完成之后,我们回到组件内部新增一个样式属性
.header{
text-decoration:dashed;
}
你可以执行pnpm run build命令进行打包,可以看到产物中自动补上了浏览器前缀,如:
._header_kcvt0_1 {
-webkit-text-decoration: dashed;
-moz-text-decoration: dashed;
text-decoration: dashed;
}