在 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 加載完成,體驗更優(比如天然支援敲空格鍵觸發),同時也更容易維護和使用,直接複制一個類名就行了。
文章來源:XboxYan_https://juejin.cn/post/7064404257436336135