最近寫了太多的邏輯代碼,寫幾行 CSS 換換腦子
一、一閃而過
很常見的效果,其實就是一個傾斜長條平移了一段距離而已
要點在於給 button 設置 overflow: hidden; 以及確保長條的初始位置和結束位置在按鈕區域外面
HTML
<button class="shiny-button">Hover Me</button>
CSS
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
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
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
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
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
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
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 特效~