【轉】CSS 實現按鈕點選動效的套路
前言
在 Web 中,大部分按鈕可能都是平平無奇的,有時候為了強調品牌特殊或者滿足特殊功能,可能需要給按鈕新增一點點選動效。比如,用過 Ant Design 的小夥伴應該都能發現,在點選按鈕的時候會有一個很微妙的水波動畫
這就非常有特色了,看到這樣的按鈕自然會聯絡上 Ant Design 。
動畫過程其實不復雜,看了一下官方的實現,是通過 js 動態更改屬性實現的,在點選的時候,改變屬性,觸發動畫,當動畫結束之後,再將該屬性還原(還原是為了保證下次點選仍然有動畫),如下
看著好像有點麻煩?其實,這種效果也是可以純 CSS 實現的,而且還能實現其他更多有趣的效果
一起看看吧~
一、CSS 過渡動畫
通常 CSS 中實現動畫有兩種思路,transition
和animation
。一般而言,簡單的、需要主動觸發(:hover
、:active
或者動態切換類名等)的可以用transition
實現,其他的都可以用animation
。
回到這個例子,動畫足夠簡單了,就兩個變化,而且需要主動觸發(這裡是點選,可以想到:active
),所以優先考慮用transition
來實現。
觀察整個動畫,其實就是兩個效果疊加而成
- 陰影不斷擴大
- 透明度不斷降低
那麼,這個動畫(過渡)的兩種狀態可以這樣來表示
/* 初始狀態 */ button{ opacity: .4; transition: .3s; } /* 擴散狀態 */ button{ box-shadow: 0 0 0 6px var(--primary-color); opacity: 0; }
嗯,兩種狀態的樣式都寫好了,怎麼觸發點選呢?
二、CSS 點選動畫
先完善一下基本樣式,假設 HTML 結構如下
<button class="button">Default</button>
簡單美化一下
:root{ --primary-color: royalblue; } .button{ padding: 5px 16px; color: #000000d9; border: 1px solid #d9d9d9; background-color: transparent; border-radius: 2px; line-height: 1.4; box-shadow: 0 2px #00000004; cursor: pointer; transition: .3s; } .button:hover{ color: var(--primary-color); border-color: currentColor; }
然後新增陰影擴散動畫,為了方便透明度的控制,這裡用::after
偽類單獨渲染
.button::after{
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
opacity: 0.4;
transition: .3s;
}
如果按照正常的思路通過:active
來觸發過渡動畫,可能會這樣來實現
.button:active::after{
box-shadow: 0 0 0 6px var(--primary-color);
opacity: 0;
}
效果如下:
嗯,好像不大對勁?接著往下看
三、CSS 過渡重置
為什麼會有上面這種現象呢?這裡提一下:active
。:active
只有在滑鼠按下時才會起作用,通常在點選一個按鈕時,都是輕輕地點選,而不是長按,如果在:active
上新增動畫,那麼在滑鼠抬起的時候,動畫一般都沒有結束,所以會導致在滑鼠抬起的時候,動畫馬上就停止了,如果是transition
,還會有一個“回退”的過渡效果。
那麼,有沒有什麼方法可以只在滑鼠抬起的時候產生動畫呢?
我的實現是這樣的,假設預設就是有陰影(透明度為0)的狀態,在:active
的時候迅速去除陰影(這裡的“迅速”,是指取消按下去的過渡動畫),然後由於預設是有過渡的,所以滑鼠抬起的時候陰影就回退到有陰影的狀態了,這樣可以保證按下去是沒有動畫的,抬起來觸發過渡動畫
整個流程其實是這樣:
取消過渡動畫也很簡單,設定時長為 0 就行了,程式碼實現就是這樣
.button::after{
/*其他樣式*/
opacity: 0;
box-shadow: 0 0 0 6px var(--primary-color);
transition: .3s;
}
/*點選*/
.button:active::after{
box-shadow: none;
opacity: 0.4;
transition: 0s; /*取消過渡*/
}
然後,神奇的效果就出來了!
這樣就實現了和 Ant Design 幾乎相同的點選效果
四、其他動效案例
上面其實提供了一種思路,只要是這種點選動畫,都可以採用這種方式來實現。比如這樣一個重新整理按鈕,需要點選的時候轉一下
用這種思路就很容易了,這個例子比上面那個要簡單一些,畢竟只有旋轉變化,沒有透明度變化,核心程式碼如下
.icon{
transform: rotate(360deg);
transition: .5s;
}
.button:active .icon{
transform: rotate(0);
transition: 0s;
}
完整程式碼可以訪問 ant design button (codepen.io),整合了更多的 demo
再比如這樣的點選粒子動效,原理也是相同的
在之前文章CSS實現一個粒子動效的按鈕中已經有講到,這裡就不多說了,完整程式碼可以訪問 button-active (codepen.io)
五、更復雜的動畫
前面提到過,簡單的動畫可以用過渡transition
來實現,那麼稍微複雜點的,比如下面這種 “Q彈Q彈” 的按鈕
這類動畫,單純的transition
就無能為力了,必須藉助animation
來實現,原理還是類似
先定義一個動畫關鍵幀
@keyframes tada {
from {
transform: scale3d(1, 1, 1)
}
10%, 20% {
transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg)
}
30%, 50%, 70%, 90% {
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg)
}
40%, 60%, 80% {
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg)
}
to {
transform: scale3d(1, 1, 1)
}
}
這個動畫來自於 Animate.css 中的 tada,直接 copy 過來就行
然後讓按鈕動起來
.button{
animation: tada 1s;
}
在點選的時候重置動畫,直接重置動畫,animation
可能會更好理解一些,這樣在抬起的時候會重新執行動畫
.button:active{
animation: none;
}
這樣就實現了,是不是出乎意料的容易?
不過有一點小瑕疵,每次頁面重新整理,按鈕會主動進行一次動畫(因為動畫是自動執行的),如下
那麼,如何避免首次進來時動畫不執行呢?
這裡有一個小技巧,可以在預設情況下設定動畫時長為 0 ,這樣在首次動畫執行後,馬上就結束了,然後在 hover
時恢復預設的動畫時長,由於動畫已經結束,改變動畫時長也不會觸發動畫再次執行,所以實現就是
.button{
animation: jump 0s;
}
.button:hover{
animation-duration: 1s;
}
.button:active{
animation: none;
}
這樣重新整理頁面就不會再有動畫了
接下來,藉助 animate.css
你可以更換任意的動畫,比如
完整程式碼可以訪問button-jump (codepen.io),整合了更多的 demo
六、總結和說明
以上就是關於 CSS 點選動畫的幾個套路和一些案例,其實就是預設執行動畫,點選時重置一下就行了。整體來說程式碼很簡單,只是理解起來可能不是特別順暢,下面總結一下實現要點:
- 簡單動畫用transition,其他用 animation
- transition 可以通過設定時長為 0 來重置
- animation 可以通過設定 none 來重置
- 在 :active 時重置動畫,點選後會再次執行動畫
- 複雜的動畫可以藉助現有的動畫庫,例如 anmate.css
- 設定動畫時長為 0 可以避免首次渲染出現動畫
相比 js 實現,CSS 實現程式碼更少,載入更快,無需等待 js 載入完成,體驗更優(比如天然支援敲空格鍵觸發),同時也更容易維護和使用,直接複製一個類名就行了。最後,如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤
原文:https://juejin.cn/post/7064404257436336135