最近做了一个纯
css
实现的流光效果,在做这个需求之前在网上找了很多示例效果,结果都不能达到我想要的效果,于是自己动手实现了下面这样的。
网上冲浪
在做这个之前就肯定是先百度,有好用的就直接复制就好了,但是网上的没有我这个光边,还有直来直去的,不能达到像我这样四面环绕的效果。
直来直去的就是只有像我这样一条边的,四面环绕的没有光边就是去掉我的光边,就是没有我这种带光边的,然后看了一下他们实现的代码,外层容器加了overflow:hidden
,这样光边肯定是不能要的了。
直来直去
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
html,
body {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #282c34;
}
.container {
background: #0e96e7;
width: 400px;
height: 4px;
position: relative;
overflow: hidden;
}
.container::before {
content: '';
position: absolute;
height: 4px;
width: 80px;
background: linear-gradient(to right, transparent, #fff);
animation: left_to_right 4s 0s infinite;
}
@keyframes left_to_right {
0% {
left: -80px;
}
100% {
left: calc(100% + 80px);
}
}
</style>
</head>
<body>
<div class="container"></div>
</body>
</html>
四面环绕没有光边
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
html,
body {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #282c34;
}
.container {
width: 400px;
height: 400px;
position: relative;
overflow: hidden;
}
.container::before {
content: '';
display: block;
width: calc(100% - 8px);
height: calc(100% - 8px);
border: 4px solid #0e96e7;
}
.line-top {
position: absolute;
width: 80px;
height: 4px;
top: 0;
left: 0;
background: linear-gradient(to right, #0e96e7, #fff);
animation: left_to_right 4s 0s linear infinite;
}
.line-right {
position: absolute;
width: 4px;
height: 80px;
top: -80px;
right: 0;
background: linear-gradient(#0e96e7, #fff);
animation: top_to_bottom 4s 3s linear infinite;
}
.line-bottom {
position: absolute;
width: 80px;
height: 4px;
bottom: 0;
right: -80px;
background: linear-gradient(to left, #0e96e7, #fff);
animation: right_to_left 4s 6s linear infinite;
}
.line-left {
position: absolute;
width: 4px;
height: 80px;
bottom: -80px;
left: 0;
background: linear-gradient(to top, #0e96e7, #fff);
animation: bottom_to_top 4s 9s linear infinite;
}
@keyframes left_to_right {
0% {
left: -80px;
}
100% {
left: calc(100% + 80px);
}
}
@keyframes top_to_bottom {
0% {
top: -80px;
}
100% {
top: calc(100% + 80px);
}
}
@keyframes right_to_left {
0% {
right: -80px;
}
100% {
right: calc(100% + 80px);
}
}
@keyframes bottom_to_top {
0% {
bottom: -80px;
}
100% {
bottom: calc(100% + 80px);
}
}
</style>
</head>
<body>
<div class="container">
<span class="line-top"></span>
<span class="line-right"></span>
<span class="line-bottom"></span>
<span class="line-left"></span>
</div>
</body>
</html>
上面的代码就不分解了,基本上长得都一样,看懂一个就都懂了,四周环绕就是直来直去的加强版。
实现光边
实现光边很简单,移除overflow:hidden
,然后加上box-shadow
是不是就好了?
上面为了演示效果,故意弄歪了,可以看到不加
overflow:hidden
的问题一下就出来了,然后box-shadow
的效果也不是很好,颜色没法过渡,和主模块的过渡也很僵硬。
处理溢出
内容溢出?假如我没有内容是不是就不会溢出了呢?那就修改动画吧。
这里长度400px
,之前的动画4s
执行完成,也就是每秒走100px
,滑块长度是80px
,这样不好计算,直接把动画改成5s
,每秒走80px
,然后掐头去尾巴,动画部分修改如下
@keyframes left_to_right {
0% {
left: 0;
width: 0;
}
20% {
left: 0;
width: 80px;
}
80% {
left: calc(100% - 80px);
width: 80px;
}
100% {
left: calc(100%);
width: 0;
}
}
完成一面,其他的面就都差不多了,这里的具体实现就不细细展开了,文尾会上完整代码,接下来是处理光边
处理光边
- 思路1
clip-path
光边使用box-shadow
无法用渐变,形状也不可控,这里是不是可以直接使用clip-path
来实现自定义的形状,然后再使用渐变色来做平滑过渡,最后再使用filter: blur
高斯模糊来模拟光边?
说干就干,奈何自己太菜,svg
的path
没研究明白,后面精进吧,不上代码了,这条路断了。
- 思路2阉割
退而求次吧,直接高斯模糊吧,形状就将就一下吧,直接加上伪类。
.line::before {
content: '';
position: absolute;
top: -8px;
left: 0;
height: 20px;
width: 100%;
background: linear-gradient(to right, transparent, #0e96e7, #fff);
filter: blur(4px);
border-radius: 0 10px 10px 0;/*这里实现一个圆头效果*/
}
效果看上去还可以,好了,开始四周环绕了,直接上代码吧
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
html,
body {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #282c34;
}
.container {
width: 400px;
height: 400px;
position: relative;
border: 1px solid #0e96e7;
}
.line-top {
position: absolute;
width: 80px;
height: 1px;
top: -1px;
left: 0;
background: linear-gradient(to right, #0e96e7, #fff);
border-radius: 50%;
animation: left_to_right 4s 0s linear infinite;
}
.line-top::before {
content: "";
position: absolute;
width: 100%;
height: 11px;
background: linear-gradient(to right, transparent, #0e96e7, #fff);
left: 0;
top: -5px;
filter: blur(4px);
z-index: -1;
}
.line-right {
position: absolute;
width: 1px;
height: 0;
top: 0;
right: -1px;
background: linear-gradient(#0e96e7, #fff);
animation: top_to_bottom 4s 3s linear infinite;
}
.line-right::before {
content: "";
position: absolute;
width: 11px;
height: 100%;
background: linear-gradient(to bottom, transparent, #0e96e7, #fff);
left: -5px;
top: 0;
filter: blur(4px);
z-index: -1;
}
.line-bottom {
position: absolute;
width: 0;
height: 1px;
bottom: -1px;
right: 0;
background: linear-gradient(to left, #0e96e7, #fff);
border-radius: 50%;
animation: right_to_left 4s 6s linear infinite;
}
.line-bottom::before {
content: "";
position: absolute;
width: 100%;
height: 11px;
background: linear-gradient(to left, transparent, #0e96e7, #fff);
left: 0;
top: -5px;
filter: blur(4px);
z-index: -1;
}
.line-left {
position: absolute;
width: 1px;
height: 0;
bottom: 0;
left: -1px;
background: linear-gradient(to top, #0e96e7, #fff);
animation: bottom_to_top 4s 9s linear infinite;
}
.line-left::before {
content: "";
position: absolute;
width: 11px;
height: 100%;
background: linear-gradient(to top, transparent, #0e96e7, #fff);
left: -5px;
top: 0;
filter: blur(4px);
z-index: -1;
}
@keyframes left_to_right {
0% {
width: 0;
left: 0;
}
25% {
left: 0;
width: 80px;
}
75% {
left: calc(100% - 80px);
width: 80px;
}
100% {
left: 100%;
width: 0;
}
}
@keyframes top_to_bottom {
0% {
top: 0;
height: 0;
}
25% {
top: 0;
height: 80px;
}
75% {
top: calc(100% - 80px);
height: 80px;
}
100% {
top: 100%;
height: 0;
}
}
@keyframes right_to_left {
0% {
right: 0;
}
25% {
width: 80px;
right: 0;
}
75% {
width: 80px;
right: calc(100% - 80px);
}
100% {
right: 100%;
width: 0;
}
}
@keyframes bottom_to_top {
0% {
bottom: 0;
}
25% {
bottom: 0;
height: 80px;
}
75% {
height: 80px;
bottom: calc(100% - 80px);
}
100% {
bottom: 100%;
height: 0;
}
}
</style>
</head>
<body>
<div class="container">
<span class="line-top"></span>
<span class="line-right"></span>
<span class="line-bottom"></span>
<span class="line-left"></span>
</div>
</body>
</html>
这里还有bug,就是转场的时候,白色一直都在,因为颜色是过渡的,这个颜色就一直都在,有一个思路就是把内容全都变成伪类,内容大小不变,外层框框
overflow:hidden
,动态大小,转场的时候把内容挤消失,这里就懒得实现了。