上次發完 不可思議的純 CSS 導航欄下划線跟隨效果 這篇文章之后,很多朋友找我討論,感嘆 CSS 的奇妙。
然后昨天,群里一位朋友問到了一個和這個效果比較類似的效果,問如何
將下面這個動畫的下划線效果,從左進入,右邊離開修改為從上方進入,下方離開。
描述很難理解,看看原本的效果:
難點所在
第一眼看到這個效果,我的內心毫無波瀾。以為只是簡單的一個下划線 hover 效果,經過友人提醒,才發現,這個動畫效果中,下划線是從一端進入,從另外一端離開的。而且,這個 hover 動畫是純 CSS 實現的。
先不考慮上面說的修改需求,先想一想,如果就是還原上述效果,僅僅使用 CSS,該如何做呢?
還原效果
嗯,正常而言,我們一個 hover 效果,可能就是從哪里來,回哪里去,大部分的應該是這樣的:
現在,難點就在於如何在 hover 離開的時候,改變動畫行進的方向。
下面我們將一個 hover 動畫分解為 3 個部分:
- hover 進入狀態
- hover 停留狀態
- hover 離開狀態
但是,對於一個 hover 效果而言,正常來說,只有初始狀態,和hover狀態兩種。可能我們的代碼是這樣:
div {
xxxx...
}
div:hover {
xxxx...
}
對於一個 hover transition 動畫,它應該是從:
- 正常狀態 -> hover狀態 -> 正常狀態 (三個步驟,兩種狀態)
所以,必須要有一種方法,能夠使得 hover 動畫的進入與離開產生兩種不一樣的效果,實現:
- 狀態1 -> hover狀態 -> 狀態2 (三個步驟,三種狀態)
實現控制動畫方向的關鍵點
所以,這里的關鍵點就在於(划重點):
使得 hover 動畫的進入與離開產生兩種不一樣的效果 。
接下來,也就是本文的關鍵所在,使用 transform: scale() 以及 transform-origin 實現這個效果。
transform: scale() 實現線條運動
transform: scale 大家應該都很熟悉了,通俗來說是用於縮放,用官方的話說,就是:
CSS 函數 scale() 用於修改元素的大小。可以通過向量形式定義的縮放值來放大或縮小元素,同時可以在不同的方向設置不同的縮放值。
這里我們使用 transform: scaleX(0) 與 transform: scaleX(1) 來改變線條的顯示與隱藏,它的 CSS 代碼簡單來看,可能是這樣:
div {
position: absolute;
width: 200px;
height: 60px;
}
div::before {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 200px;
height: 2px;
background: deeppink;
transition: transform .5s;
transform: scaleX(0);
}
div:hover::before {
transform: scaleX(1);
}
嗯?為什么是要用 transform: scale() 來實現線條的動畫?因為它可以配合 transform-origin 實現動畫的不同運動方向:
transform-origin 實現線條運動方向
transform-origin 讓我們可以更改一個元素變形(transform)的原點,transform-origin 屬性可以使用一個,兩個或三個值來指定,其中每個值都表示一個偏移量。 沒有明確定義的偏移將重置為其對應的初始值。
本效果最最最重要的地方就在於這里,我們使用 transform-origin 去改變 transform: scale() 的原點實現線條運動的方向。
- 我們給線條設置一個默認的
transform-origin記為狀態1 - hover 的時候,設置另外一個不同的
transform-origin, 記為狀態2
所以,當然我們 hover 的時候,會讀取狀態2的transform-origin,從該原點開始放大至 scaleX(1),hover 離開的時候,會讀取狀態1的transform-origin,從scaleX(1)狀態縮小至該原點。
嗯,CSS代碼大概是這樣:
div {
position: absolute;
width: 200px;
height: 60px;
}
div::before {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 200px;
height: 2px;
background: deeppink;
transition: transform .5s;
transform: scaleX(0);
transform-origin: 100% 0;
}
div:hover::before {
transform: scaleX(1);
transform-origin: 0 0;
}
這里,我們巧妙的通過 hover 狀態施加了一層新的 transform-origin ,讓動畫的進入與離開產生了兩種不同的效果,兩個不同的方向。
如此一來,也就順利實現了我們想要的效果,撒花:
注意,這里使用了 transform-origin 去改變 transform: scale() 的原點實現線條運動的方向,而沒有借助諸如 position 位移,transform: translate(),或者 margin 等位置屬性去改變線條所在的位置。
所以,有趣的是,線條其實沒有產生過任何位移,這里其實也是障眼法,讓它看上去,它好像在移動。
拓展延伸
嗯,有了上述方法,也就是 transform: scale() 配合 transform-origin ,我們可以開始隨意改變動畫的初始與結束狀態了。把他們運用到其他效果之上,簡單的幾個示意效果:
值得注意的點
還有幾個點是比較有意思的,大家可以嘗試嘗試,思考思考:
- 嘗試改變兩種狀態的
transition-timing-function緩動函數,可以讓動畫更加流暢具有美感; - 注意一下,線條的
transition設置的是transition: transform .5s而不是transition: all .5s,體驗一下兩種寫法所產生的不同效果。
最后
本方法我個人最早見於 Css菜單懸停效果。如果你有更好的方法歡迎提出共同探討。
更多精彩 CSS 技術文章匯總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。
好了,本文到此結束,希望對你有幫助 :)
如果還有什么疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。
我的博客即將搬運同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=3ly2fi88twowo






