前端工程化_CSS 工具链_学习笔记
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 Modules
generateScopedName: '[name]__[local]___[hash:base64:5]',
},
},
};
我的结构是这样的
可以看到编译后类名变了
同时还会出来 json 做类名映射
这个又有加厂商前缀
这就是 postcss
tailwind
tailwind:称为原子化 CSS,是基于 postcss 的一个插件
这三行编译完就是这么多内容
这就是插件能力
END
本文主要介绍了 CSS 工具链,可以看出工具链的出现都是为了解决语言的问题,文中就介绍了预处理器和后处理器,预处理器主要介绍了 sass,并举了星空这个例子,sass 是通过与预编译器编译成 css 后给 html 使用;后处理器则介绍了 postcss,其中 postcss 和 babel 类似,都有很多插件,简单介绍了一下 tailwind 这个原子化 CSS,它也是 postcss 的一个插件