持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第N天,点击查看活动详情
前言
上一篇 CSS进阶向--纯css实现流光边框 实现了一个类似激光灯带的按钮边框效果,但是使用了四个 span 标签来模拟按钮边框,并且不同位置的边框对应的 css 样式与 animation 动画都需要单独配置,可能会增加一定的开发和调试成本。
所以这一节我们利用背景图片来实现一个流光效果的边框。先上代码和最终效果:
然后,我们开始分步编写:
1. 逻辑拆解和设计
我们先对该实现方式的大体逻辑进行拆分:
首先,需要一个背景图片(颜色)来持续旋转,模拟边框的颜色变化,此时该元素背景颜色一般会铺满或者占据部分整体(最外层) dom 元素,所以内部还需要一个元素来继承外部的背景色,用来覆盖背景图片颜色部分,保证只有一个“边框”透出颜色;为了保证具有背景颜色的部分不会超出我们预设的 dom 元素区域,所以外层 dom 还需要隐藏内部元素的超出部分。
为了减少 dom 标签,模拟边框的带背景图片元素还可以使用 伪类 来实现。
所以整体的 dom 结构如下:
<div class="streamer-button">
<!-- ::before -->
<div class="streamer-content">Streamer Frame Button 2</div>
</div>
其中:
- div.streamer-button 作为最外层元素,负责基础样式和隐藏内部元素超出部分
- div.streamer-button::before 作为背景图片(颜色)的挂载元素,并添加动画来模拟“流光”效果
- div.streamer-content 作为文本内容区域,需要继承外部背景色来覆盖 before 伪元素的背景图片(颜色)
为了保证元素层级,还需要给元素添加定位配置。
2. 背景与动画
我们先处理外层元素与伪元素的样式部分。
首先,定义一个基础背景色变量,用来表示最外层通用背景颜色,并设置 body 样式(这里只是为了演示效果,实际上不需要设置 body 样式):
@property --bg-color {
syntax: "<color>";
initial-value: #010101;
inherits: false;
}
body {
height: 100vh;
background: var(--bg-color);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
然后,配置 div.streamer-button 与 div.streamer-button::before 的基础样式:
.streamer-button {
background: var(--bg-color);
padding: 4px;
position: relative;
border-radius: 8px;
justify-content: center;
align-items: center;
text-align: center;
display: flex;
font-size: 1.5em;
color: rgb(88 199 250 / 100%);
cursor: pointer;
font-family: cursive;
}
.streamer-button::before {
content: "";
background-image: linear-gradient(132deg, #5ddcff, #3c67e3 43%, #4e00c2);
position: absolute;
z-index: 0;
left: -4px;
right: -4px;
padding-bottom: calc(100% + 8px);
}
此时,我们得到了这样一个效果:
通过元素审查会发现 before 伪类已经超出了父元素,所以需要给父元素增加一个 overflow: hidden。就可以得到正确效果
然后,我们再来实现旋转动画,并将动画添加到 before 伪元素上:
@keyframes spin {
0% {
rotate: 0deg;
}
100% {
rotate: 360deg;
}
}
.streamer-button::before {
animation: spin 2s linear infinite;
}
最后,给内层元素添加一个背景色和需要的基础样式即可:
.streamer-content {
padding: 24px 40px;
background: var(--bg-color);
z-index: 10;
border-radius: 6px;
}
3. Tips
本节除了提供另外一种实现流光边框的效果外,也有一些其他的小技巧:
3.1 padding 实现固定宽高比元素
因为 padding 的四个值如果是百分比形式,则都是以该元素的 父元素 的 ”横向“ 宽度作为基础单位进行计算的,所以我们可以利用这个特性来实现一个固定宽高比的元素。
<div class="parent">
<div class="rectangle"></div>
</div>
<style type="text/css">
.parent {
width: 400px;
height: auto;
}
.rectangle {
width: 200px;
padding-bottom: 60%;
}
</style>
此时, div.rectangle 的高度则为 **400 * 0.6 = 240 px **。
最后我们在 div.rectangle 内部使用 “相对定位+绝对定位” 即可实现固定宽高比例。本节里面的伪类就是采用这种方式,避免高度不够导致旋转时无法正常模拟边框。
3.2 animation-play-state 控制动画状态
该属性具有两个值:paused 和 running。
其中 **paused ** 表示暂停动画,running 表示正常执行动画过程。
为了减少一些动画效果对文本阅读的影响,可以在 hover 状态下添加 animation-play-state: paused; 停止动画。
3.3 css @property 自定义属性
该属性是一个实验性属性,允许用户 显示的定义 需要的自定义属性,包含三个部分:属性类型检查、设定默认值以及定义该自定义属性是否可以被继承。
语法如下:
@property --property-name {
syntax: '<color>';
inherits: false;
initial-value: #c0ffee;
}
具体说明可以查看以下文档:
chokcoco - CSS @property,让不可能变可能