css 越来越强大了,现在即使不使用 javascript 也能各种各样炫酷的动画效果

比如使用 css 阴影来实现一个星空背景的效果

思路

我们知道,星星看起来就是一个个的小点或者说一个个很小的粒子,在前端要表示一个很小的粒子,只需要一个大小为 1px 左右的 div 标签并带上一个颜色就可以实现了

但是要实现一个星空的话是需要很多粒子的,如果全部使用 1px 的元素,那么页面就会因为这个背景效果从而向 dom 插入过多元素

这时候就可以使用到 box-shadow 这个属性了

box-shadow 是一个 CSS 属性,它可以向一个元素添加一个或多个阴影,如果给一个很小的元素添加阴影,那么阴影看起来就就会是一个小点,如果给元素添加多个阴影是不是就可以实现多个小点

至于要实现星空粒子大小参差不齐的话,是不是可以改变元素的大小,比如 2px,那么生成的粒子效果就会稍微大一些

要让星空背景滚动起来的话,可以使用 css 动画,让元素沿着 Y 轴进行移动,阴影也会随着移动,这样就实现了滚动效果

代码

界面结构

首先我们准备好一个基本的 html 界面

页面中有三个 div,分别代表三个不同的大小的星星

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>

<body>
<div class="star"></div>
<div class="medium-star"></div>
<div class="big-star"></div>
</body>
</html>

接着我们准备好样式

样式

往 head 标签中添加一个 style 标签并编写以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<style>
/* 去除默认边距 */
* {
margin: 0;
padding: 0;
}

/* 设置body撑满整个页面,并定义一个背景的生成大小 */
html,
body {
height: 100%;
--starSize: -2000px;
}

/* body的背景颜色 */
body {
background: radial-gradient(ellipse at bottom, #182735 0%, #090a0f 100%);
}

/* 小星星,大小为1px */
.star {
height: 1px;
width: 1px;
background: transparent;
animation: star infinite 80s linear;
}

/* 中星星,大小为2px */
.medium-star {
height: 2px;
width: 2px;
background: transparent;
animation: star infinite 120s linear;
}

/* 大星星,大小为3px */
.big-star {
height: 3px;
width: 3px;
background: transparent;
animation: star infinite 150s linear;
}

/* 定义滚动动画,从opx移动到-2000px,就是向上移动2000px */
@keyframes star {
0% {
transform: translateY(0);
}

100% {
transform: translateY(var(--starSize));
}
}
</style>

脚本

然后我们在 body 插入一个 script 标签,并编写以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script>
// 获取三个星星元素
const star = document.querySelector(".star");
const mediumStar = document.querySelector(".medium-star");
const bigStar = document.querySelector(".big-star");
// 定义星星位置的最大偏移量
const starSize = 2000;
// 阴影生成函数
const shadowStr = (count) => {
// 定义阴影背景字符串
let str = `${Math.random() * starSize}px ${
Math.random() * starSize
}px #fff`;
for (let i = 0; i < count; i++) {
// 每次循环生成一个阴影,并拼接到字符串中
str += `,${Math.random() * starSize}px ${
Math.random() * starSize
}px #fff`;
}
return str;
};
// 调用阴影生成函数生成阴影,并将元素的阴影设置为生成的阴影
star.style.boxShadow = shadowStr(700);
mediumStar.style.boxShadow = shadowStr(400);
bigStar.style.boxShadow = shadowStr(100);
</script>

效果预览

总代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}

html,
body {
height: 100%;
--starSize: -2000px;
}

body {
background: radial-gradient(
ellipse at bottom,
#182735 0%,
#090a0f 100%
);
}

.star {
height: 1px;
width: 1px;
background: transparent;
animation: star infinite 80s linear;
}

.medium-star {
height: 2px;
width: 2px;
background: transparent;
animation: star infinite 120s linear;
}

.big-star {
height: 3px;
width: 3px;
background: transparent;
animation: star infinite 150s linear;
}

@keyframes star {
0% {
transform: translateY(0);
}

100% {
transform: translateY(var(--starSize));
}
}
</style>
</head>

<body>
<div class="star"></div>
<div class="medium-star"></div>
<div class="big-star"></div>
<script>
const star = document.querySelector(".star");
const mediumStar = document.querySelector(".medium-star");
const bigStar = document.querySelector(".big-star");
const starSize = 2000;
const shadowStr = (count) => {
let str = `${Math.random() * starSize}px ${
Math.random() * starSize
}px #fff`;
for (let i = 0; i < count; i++) {
str += `,${Math.random() * starSize}px ${
Math.random() * starSize
}px #fff`;
}
return str;
};
star.style.boxShadow = shadowStr(700);
mediumStar.style.boxShadow = shadowStr(400);
bigStar.style.boxShadow = shadowStr(100);
</script>
</body>
</html>

进阶

其实你还可以添加一个 X 轴移动动画,让星星在 X 轴上移动,这样看起来更加真实

如果要实现无缝滚动,那么就需要设置两个星空背景,比如一个背景的滚动范围是 0 ~ 2000px,另一个背景就可以是 2000 ~ 4000px 让其中一个星空背景滚动完成后消失在视野中,另一个星空背景继续滚动,这样就实现了无缝滚动效果