CSS 工具链
css 呢,有以下两个缺点
1.语法缺失(循环、判断、拼接)
2.功能缺失(颜色函数、数学函数、自定义函数)
虽然 CSS 支持几个函数,比如:
url('')
用于引入外部资源
calc()
计算函数,计算尺寸、间距等
linear-gradient
渐变函数
但还是太少了
这时候有人就创造了新语言
新语言是 CSS 的超集
新语言 -编译器-> CSS语言
本文讲一讲 sass
sass/less/stylus -CSS预编译器-> CSS语言
预处理器
body{background-color: #f40;
}
写了一个纯粹的 CSS 代码
然后需要用到预编译器
使用命令下载
npm i -g sass
然后就可以使用 sass 这个命令了,这里需要注意 node 版本不能太低,需要12以上,我这里用的是18

使用命令转换
sass 1.scss 1.css

生成了两个,一个是 CSS,一个是源码地图,是用于调试的,下一篇博文也会提到
使用命令
sass 1.scss 1.css --no-source-map
就会生成源码地图了

目前左右没用区别
下面可以使用变量
sass 1.scss 1.css --no-source-map -w
watch 表示监听文件的变化

下面来用 sass 写一个星空背景
sass index.scss index.css -w --no-source-map
其中 html 代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./index.css">
</head>
<body><div class="layer1"></div><div class="layer2"></div><div class="layer3"></div><div class="title">星空</div>
</body>
</html>
当前效果

设置阴影
html {height: 100%;background: radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%);overflow: hidden;
}.title {position: absolute;top: 50%;left: 0;right: 0;color: #fff;text-align: center;font-family: "lato", sans-serif;font-weight: 300;font-size: 50px;letter-spacing: 10px;margin-top: -60px;padding-left: 10px;background: linear-gradient(white, #38495a);background-clip: text;-webkit-background-clip: text;color: transparent;
}.layer1 {$size: 100px;position: fixed;width: $size;height: $size;border-radius: 50%;left: 0;right: 0;background-color: #fff;box-shadow: 10vw 10vh #fff;
}

阴影是可以设置多个的
box-shadow: 10vw 10vh #fff, 20vw 20vh #fff, 30vw 30vh #fff, 40vw 40vh #fff;

那这样就有一个思路了,能不能做成一个循环,循环的生成这些阴影,像 js 就一个 for 搞定,可是 css 没有循环
但是 scss 里面有循环,可以自定义函数
这个函数要做的无非是字符串的拼接
js 中用的是 $,这里是 #
@function createShadow($n){$shadow:'10vw 10vh #fff';@for $i from 2 through $n {$shadow: '#{$shadow}, 10vw 10vh #fff';}@return $shadow;
}
因为拼接的是字符串,所以返回带了“”,用 sass 里面的 unquote 去掉双引号

可以看到现在都是偏移同一个量
@function createShadow($n) {$shadow: '#{random(100)}vw #{random(100)}vh #fff';@for $i from 2 through $n {$shadow: '#{$shadow}, #{random(100)}vw #{random(100)}vh #fff';}@return unquote($shadow);
}
改成这样,生成0-100随机数

然后把星星改成一个像素即可

有那味了
那么接下来就是星星的往上移动
.layer1 {$size: 4px;position: fixed;width: $size;height: $size;border-radius: 50%;left: 0;right: 0;background-color: #fff;box-shadow: createShadow(200);animation: moveUp 5s linear infinite;
}@keyframes moveUp{100%{transform: translateY(-100vh);}
}
现在的问题就是星星只移动一半,星星底移动到视口顶之后再回到原来位置

这样处理就可以了,复制一份星星
可以把下面的星星作为上面的子元素
&::after {content: '';position: fixed;left: 0;top: 100vh;width: inherit;height: inherit;border-radius: inherit;box-shadow: inherit;}

这样添加

稳稳的,没有问题了
搞定了一个层之后,我们要搞定多个层
那么就希望循环生成选择器
@for $i from 1 through 3 {.layer#{$i} {$size: 1px;position: fixed;width: $size;height: $size;border-radius: 50%;left: 0;right: 0;box-shadow: createShadow(200);animation: moveUp 5s linear infinite;&::after {content: '';position: fixed;left: 0;top: 100vh;width: inherit;height: inherit;border-radius: inherit;box-shadow: inherit;}}
}
这下可以 layer1、2、3了

然后是处理星星个数和星星大小
$count: 1000;@for $i from 1 through 3 {$count: floor(calc($count/2));@debug $count;.layer#{$i} {$size: #{$i}px;position: fixed;width: $size;height: $size;border-radius: 50%;left: 0;right: 0;box-shadow: createShadow($count);animation: moveUp 5s linear infinite;&::after {content: '';position: fixed;left: 0;top: 100vh;width: inherit;height: inherit;border-radius: inherit;box-shadow: inherit;}}
}
这样处理,越大的星星就越少
再改一下时间
$count: 1000;
$duration:400s;
@for $i from 1 through 3 {$count: floor(calc($count/2));$duration:floor(calc($duration/2));@debug 'count: #{$count}';@debug 'duration: #{$duration}';.layer#{$i} {$size: #{$i}px;position: fixed;width: $size;height: $size;border-radius: 50%;left: 0;right: 0;box-shadow: createShadow($count);animation: moveUp $duration linear infinite;&::after {content: '';position: fixed;left: 0;top: 100vh;width: inherit;height: inherit;border-radius: inherit;box-shadow: inherit;}}
}
啪的一下,像模像样了


显然 css 的代码比 scss 代码多了很多,这就是工程化的意义
SCSS 的出现让我们可以使用到很多的新语法和新功能,从而增强 CSS 目的,提升我们的开发效率
后处理器
后处理器:
- 厂商前缀:autoprefixer
- 代码压缩:cssnano
- 代码剪枝:purgecss
- 类名冲突:css module
不管是预处理器还是后处理器,做的都是转换
转换就是这些东西的共同逻辑
比如说日期选择的组件,其实就是在做抽象
对于日期选择进一步抽象就是下拉选择/下拉框+日期选择
抽象下拉框就不仅适用于日期选择了,也可以下拉列表等等
做出通用的下拉框就是更高级别的抽象
再抽象,触发+弹出

这其实和 JS 里面的 babel 逻辑是一样的
使用命令
npm install --save-dev postcss postcss-cli

来了,postcss、postcss-cli 其实和 babel-core、babel-cli 是可以类比的
npm install --save-dev postcss postcss-cli postcss-modules postcss-preset-env tailwindcss autoprefixer
package.json 加上内容
{"name": "basic","version": "1.0.0","description": "","main": "index.js","scripts": {"compile": "postcss src/**/*.css -d dist -w --no-map"},"keywords": [],"author": "","license": "ISC","devDependencies": {"autoprefixer": "^10.4.20","postcss": "^8.4.49","postcss-cli": "^11.0.0","postcss-modules": "^6.0.1","postcss-preset-env": "^10.1.2","tailwindcss": "^3.4.16"}
}
tailwind.config.js 也配置一下
module.exports = {content: ["./src/**/*.{html,js,jsx,ts,tsx,css}", // 扫描 src 目录下的所有文件"./public/index.html", // 包括 HTML 文件],theme: {extend: {},},plugins: [],
};
postcss.config.js 也配置一下
module.exports = {plugins: {'postcss-preset-env': { stage: 1 }, // 支持最新的 CSS 特性'tailwindcss': {}, // TailwindCSS 支持'autoprefixer': {}, // 添加浏览器前缀'postcss-modules': { // 启用 CSS ModulesgenerateScopedName: '[name]__[local]___[hash:base64:5]',},},};
我的结构是这样的

可以看到编译后类名变了

同时还会出来 json 做类名映射

这个又有加厂商前缀

这就是 postcss
tailwind
tailwind:称为原子化 CSS,是基于 postcss 的一个插件

这三行编译完就是这么多内容
这就是插件能力
END
本文主要介绍了 CSS 工具链,可以看出工具链的出现都是为了解决语言的问题,文中就介绍了预处理器和后处理器,预处理器主要介绍了 sass,并举了星空这个例子,sass 是通过与预编译器编译成 css 后给 html 使用;后处理器则介绍了 postcss,其中 postcss 和 babel 类似,都有很多插件,简单介绍了一下 tailwind 这个原子化 CSS,它也是 postcss 的一个插件