七种通过 CSS 实现的按钮 Hover 特效
最近写了太多的逻辑代码,写几行 CSS 换换脑子
一、一闪而过
很常见的效果,其实就是一个倾斜长条平移了一段距离而已
要点在于给 button 设置 overflow: hidden; 以及确保长条的初始位置和结束位置在按钮区域外面
HTML
<button class="shiny-button">Hover Me</button>
CSS
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
button {
background: transparent;
border: none;
cursor: pointer;
}
button.shiny-button {
color: #fff;
border: 1px solid #fff;
padding: 8px 40px;
position: relative;
overflow: hidden; /* 非常重要 */
}
.shiny-button::after {
content: '';
display: block;
position: absolute;
top: -120px;
left: -80px;
width: 36px;
height: 360px;
background: #fff;
opacity: 0.16;
transform: rotate(-45deg);
transition: all 500ms ease-out;
}
.shiny-button:hover::after {
left: 200%;
}
二、两极翻转
在 Hover 的时候执行 X 轴翻转,然后切换文本
这里的关键点在于使用 backface-visibility: hidden; 隐藏翻转到背面的文本
HTML
<button class="flip-button">
<div class="flex-center flip-text front">Hover Me</div>
<div class="flex-center flip-text back">Hello Wise.Wrong</div>
</button>
CSS
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
button {
background: transparent;
border: none;
cursor: pointer;
}
.flex-center {
display: flex;
justify-content: center;
align-items: center;
}
button.flip-button {
color: #fff;
border: 1px solid #fff;
position: relative;
width: 200px;
height: 40px;
}
.flip-text {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
transition: all 600ms ease-in-out;
transform-style: preserve-3d;
backface-visibility: hidden;
}
.flip-text.back {
transform: rotateX(0.5turn);
}
.flip-button:hover .flip-text {
transform: rotateX(0.5turn);
}
.flip-button:hover .flip-text.back {
transform: rotateX(0turn);
}
三、单向填充
这个效果实现的方案就很很多了,比如设置伪元素 after 宽度从 0 过渡为 100%
不过个人更喜欢用背景 background 来实现
HTML
<button class="fill-button">Hover Me</button>
CSS
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
button {
--bg-color: #555660;
--font-color: #fff;
background-color: transparent;
border: none;
cursor: pointer;
transition: var(--transition-config);
}
button.fill-button {
color: var(--font-color);
border: 1px solid var(--font-color);
position: relative;
padding: 8px 40px;
transition: all 600ms ease-out;
/* 以下为核心代码 */
background-size: 200% 100%;
background-position: right bottom;
background-image: linear-gradient(to right, var(--font-color) 50%, var(--bg-color) 50%);
}
button.fill-button:hover {
color: var(--bg-color);
background-position: left bottom;
}
四、径向扩散
创建一个圆形的背景层,然后通过 scale 放大
调整背景层的圆心位置,还可以实现从矩形角落放大
HTML
<button className="radial-button">Hover Me</button>
CSS
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
html {
--font-color: #fff;
--bg-color: rgba(255, 255, 255, 0.4);
}
button {
background-color: transparent;
border: none;
cursor: pointer;
}
button.radial-button {
position: relative;
overflow: hidden;
z-index: 1;
border: 1px solid var(--font-color);
color: var(--font-color);
padding: 12px 40px;
}
.radial-button::before {
content: '';
position: absolute;
z-index: -1;
top: 50%;
left: 50%;
width: 1em;
height: 1em;
border-radius: 50%;
background-color: var(--bg-color);
transform-origin: center;
transform: translate3d(-50%, -50%, 0) scale(0, 0);
transition: transform 500ms ease-in-out;
}
.radial-button:hover::before {
transform: translate3d(-50%, -50%, 0) scale(15, 15);
}
五、组成边框
创建四条边框线,然后用定位改变他们的位置
HTML
<div class="line-button-wrapper">
<button class="line-button">Hover Me</button>
<div class="line-gourp">
<div class="line line-top"></div>
<div class="line line-left"></div>
<div class="line line-right"></div>
<div class="line line-bottom"></div>
</div>
</div>
CSS
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
html {
--font-full-color: #fff;
--font-color: rgba(255, 255, 255, 0.8);
}
button {
background-color: transparent;
border: none;
cursor: pointer;
}
button.line-button {
position: relative;
z-index: 2;
color: var(--font-color);
padding: 12px 40px;
border: 1px solid transparent;
}
.line-button-wrapper {
position: relative;
display: inline-block;
}
.line-button-wrapper .line-button,
.line-button-wrapper .line {
transition: all 600ms ease-out;
}
.line-button-wrapper:hover .line-button {
color: var(--font-full-color);
}
.line-button-wrapper:hover .line-gourp .line {
opacity: 1;
transform: translate(0, 0);
}
.line-gourp,
.line-gourp .line {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
}
.line-gourp .line {
border: 1px solid transparent;
opacity: 0;
}
.line.line-top {
border-top-color: var(--font-full-color);
bottom: auto;
transform: translateX(-50%);
}
.line.line-bottom {
border-bottom-color: var(--font-full-color);
top: auto;
transform: translateX(50%);
}
.line.line-left {
border-left-color: var(--font-full-color);
right: auto;
transform: translateY(80%);
}
.line.line-right {
border-right-color: var(--font-full-color);
left: auto;
transform: translateY(-80%);
}
六、逐帧动画
这个效果来自旧版的 B 站,下文展示的相关代码也是从 B 站的源码中 copy 而来
首先需要一张逐帧平铺的长图(下图),然后通过动画 animation 中的 steps 方法调整长图 background-position,最终实现动图
HTML
<button class="rocket-button"></button>
CSS
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
button {
background-color: transparent;
border: none;
cursor: pointer;
}
button.rocket-button {
background-image: url("https://static.hdslb.com/bl2se/images/rocket_frame.png");
width: 150px;
height: 175px;
background-position-x: -600px;
}
.rocket-button:hover {
animation: fly 0.4s steps(1) infinite;
}
@keyframes fly {
0% {
background-position-x: 0;
}
25% {
background-position-x: -150px;
}
50% {
background-position-x: -300px;
}
75% {
background-position-x: -450px;
}
to {
background-position-x: -600px;
}
}
七、七十二变
这也是通过逐帧动画来实现的,但关键点在于,需要通过 animation-play-state 来控制动画的暂停与播放
此外还可以通过设置 animation-delay 为负值,来控制初始显示的图标
HTML
<button class="random-button">
Hover Me
<span class="random-button-icon"></span>
</button>
CSS
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
html {
--icon-height: 30px;
}
button {
background-color: transparent;
border: none;
cursor: pointer;
}
button.random-button {
color: #fff;
border: 1px solid #fff;
padding: 12px 40px;
}
.random-button-icon {
width: 22px;
height: var(--icon-height);
margin-left: 4px;
overflow: hidden;
display: inline-block;
vertical-align: middle;
position: relative;
}
.random-button-icon::after {
content: '😂😠😎😳😡😭😀🙄😷😱';
display: block;
font-size: 20px;
line-height: var(--icon-height);
transform: translateY(0);
/* 声明动画效果 */
animation: random-icon 2s steps(1) infinite;
/* 暂停动画 */
animation-play-state: paused;
/* 通过负值延迟来设置初始显示的 Icon */
animation-delay: -0.4s;
}
.random-button:hover .random-button-icon::after {
/* hover 的时候播放动画 */
animation-play-state: running;
}
@keyframes random-icon {
0% {
transform: translateY(0);
}
10% {
transform: translateY(-30px);
}
20% {
transform: translateY(-60px);
}
30% {
transform: translateY(-90px);
}
40% {
transform: translateY(-120px);
}
50% {
transform: translateY(-150px);
}
60% {
transform: translateY(-180px);
}
70% {
transform: translateY(-210px);
}
80% {
transform: translateY(-240px);
}
90% {
transform: translateY(-270px);
}
to {
transform: translateY(-300px);
}
}
我这里是通过伪元素的 content 添加了一串 emoji 表情
也可以像上面的“逐帧动画”那样直接设置一个背景长图,然后通过 background-position 来控制每一帧的内容
另外推荐一个 GitHub 仓库:Hover-Buttons,分享了很多 hover 特效~