巧妙地制作背景色漸變動畫
通過本文,你能了解到 4 種不一樣的,使用純 CSS 制作的漸變背景的過渡動畫的方式。
有的時候,我們可能需要下面這樣的動畫效果,漸變背景色的過渡動畫:
漸變背景的過渡動畫
假設(shè)我們漸變的寫法如下:
- div {
- background: linear-gradient(90deg, #ffc700 0%, #e91e1e 100%);
- }
按照常規(guī)想法,配合 animation ,我們首先會想到在 animation 的步驟中通過改變顏色實現(xiàn)顏色漸變動畫,那么我們的 CSS 代碼可能是:
- div {
- background: linear-gradient(90deg, #ffc700 0%, #e91e1e 100%);
- animation: gradientChange 2s infinite;
- }
- @keyframes gradientChange {
- 100% {
- // 漸變中的顏色發(fā)生了變化
- background: linear-gradient(90deg, #e91e1e 0%, #6f27b0 100%);
- }
- }
上面我們用到了三種顏色:
- #ffc700 黃色
- #e91e1e 紅色
- #6f27b0 紫色
最后,并沒有我們預(yù)期的結(jié)果,而是這樣的:
CodePen Demo - linear-graident 變換的動畫效果[1]
我們預(yù)期的過渡動畫,變成了逐幀動畫。
也就是說,線性漸變是不支持動畫 animation 的。
那單純的由一個顏色,變化到另外一個顏色呢?像下面這樣:
- div {
- background: #ffc700;
- animation: gradientChange 3s infinite alternate;
- }
- @keyframes gradientChange {
- 100% {
- background: #e91e1e;
- }
- }
我們發(fā)現(xiàn),單純的單色值之間的變化是可以發(fā)生漸變的:
單色漸變
部分屬性是不支持直接整個進(jìn)行過渡動畫的
總結(jié)一下,線性漸變(徑向漸變、角向漸變)是不支持 animation 的,單色的 background 是支持的。
查找了下文檔,在 background 附近區(qū)域截圖如下:
哪些 CSS 屬性可以動畫?[2],上面的截圖是不完整的支持 CSS 動畫的屬性,完整的可以戳左邊。
對于 background 相關(guān)的,文檔里寫的是支持 background 但是沒有細(xì)說不支持 background: linear-gradient()/radial-gradient() 。
那么是否我們想要的背景色漸變動畫就無法實現(xiàn)了呢?下面我們就發(fā)散下思維看看有沒有其他方式可以達(dá)到我們的目標(biāo)。
通過 background-position 模擬漸變動畫
上面哪些 CSS 屬性可以動畫的截圖中,列出了與 background 相關(guān)還有 background-position,也就是 background-position 是支持動畫的,通過改變 background-position 的方式,可以實現(xiàn)漸變動畫:
- div {
- background: linear-gradient(90deg, #ffc700 0%, #e91e1e 50%, #6f27b0 100%);
- background-size: 200% 100%;
- background-position: 0 0;
- animation: bgposition 2s infinite linear alternate;
- }
- @keyframes bgposition {
- 0% {
- background-position: 0 0;
- }
- 100% {
- background-position: 100% 0;
- }
- }
這里我們還配合了 background-size。首先了解下:
- background-position:指定圖片的初始位置。這個初始位置是相對于以 background-origin 定義的背景位置圖層來說的。
- background-size:設(shè)置背景圖片大小。當(dāng)取值為百分比時,表示指定背景圖片相對背景區(qū)的百分比大小。當(dāng)設(shè)置兩個參數(shù)時,第一個值指定圖片的寬度,第二個值指定圖片的高度。
通過 background-size: 200% 100% 將圖片的寬度設(shè)置為兩倍背景區(qū)的寬度,再通過改變 background-position 的 x 軸初始位置來移動圖片,由于背景圖設(shè)置的大小是背景區(qū)的兩倍,所以 background-position 的移動是由 0 0 -> 100% 0 。
通過 background-size 模擬漸變動畫
既然 background-position 可以,那么另一個 background-size 當(dāng)然也是不遑多讓。與上面的方法類似,只是這次 background-position 輔助 background-size ,CSS 代碼如下:
- div {
- background: linear-gradient(90deg, #ffc700 0%, #e91e1e 33%, #6f27b0 66%, #00ff88 100%);
- background-position: 100% 0;
- animation: bgSize 5s infinite ease-in-out alternate;
- }
- @keyframes bgSize {
- 0% {
- background-size: 300% 100%;
- }
- 100% {
- background-size: 100% 100%;
- }
- }
CodePen--Demo--position-size 實現(xiàn)漸變動畫[3]
通過改變 background-size 的第一個值,我將背景圖的大小由 3 倍背景區(qū)大小向 1 倍背景區(qū)大小過渡,在背景圖變換的過程中,就有了一種動畫的效果。
而至于為什么要配合 background-position: 100% 0 。是由于如果不設(shè)置 background-position ,默認(rèn)情況下的值為 0% 0%,會導(dǎo)致動畫最左側(cè)的顏色不變,像下面這樣,不大自然:
通過 transform 模擬漸變動畫
上面兩種方式雖然都可以實現(xiàn),但是總感覺不夠自由,或者隨機(jī)性不夠大。
不僅如此,上述兩種方式,由于使用了 background-position 和 background-size,并且在漸變中改變這兩個屬性,導(dǎo)致頁面不斷地進(jìn)行大量的重繪(repaint),對頁面性能消耗非常嚴(yán)重,所以我們還可以試試 transfrom 的方法:
下面這種方式,使用偽元素配合 transform 進(jìn)行漸變動畫,通過元素的偽元素 before 或者 after ,在元素內(nèi)部畫出一個大背景,再通過 transform 對偽元素進(jìn)行變換:
- div {
- position: relative;
- overflow: hidden;
- width: 100px;
- height: 100px;
- margin: 100px auto;
- border: 2px solid #000;
- &::before {
- content: "";
- position: absolute;
- top: -100%;
- left: -100%;
- bottom: -100%;
- right: -100%;
- background: linear-gradient(45deg, #ffc700 0%, #e91e1e 50%, #6f27b0 100%);
- background-size: 100% 100%;
- animation: bgposition 5s infinite linear alternate;
- z-index: -1;
- }
- }
- @keyframes bgposition {
- 0% {
- transform: translate(30%, 30%);
- }
- 25% {
- transform: translate(30%, -30%);
- }
- 50% {
- transform: translate(-30%, -30%);
- }
- 75% {
- transform: translate(-30%, 30%);
- }
- 100% {
- transform: translate(30%, 30%);
- }
- }
實現(xiàn)原理如下圖所示:
CodePen--Demo--偽元素配合transform實現(xiàn)背景漸變[4]
上面列出來的只是部分方法,理論而言,偽元素配合能夠產(chǎn)生位移或者形變的屬性都可以完成上面的效果。我們甚至可以運用不同的緩動函數(shù)或者借鑒蟬原則,制作出隨機(jī)性十分強的效果。
當(dāng)然,本文羅列出來的都是純 CSS 方法,使用 SVG 或者 Canvas 同樣可以制作出來,而且性能更佳。感興趣的讀者可以自行往下研究。
通過濾鏡 hue-rotate 實現(xiàn)漸變動畫(更新于2019/04/06)
下面這個方法,可謂是新時代的利器。
通過濾鏡 hue-rotate,可以非常方便的實現(xiàn)背景色漸變動畫,過渡效果也非常的自然,代碼量也少,可以稱得上是黑科技了:
- div {
- background: linear-gradient(45deg, #ffc107, deeppink, #9c27b0);
- animation: hueRotate 10s infinite alternate;
- }
- @keyframes hueRotate {
- 0 {
- filter: hue-rotate(0);
- }
- 100% {
- filter: hue-rotate(360deg);
- }
- }
CodePen Demo -- hue-rotate實現(xiàn)漸變背景動畫[5]
使用 CSS @property 實現(xiàn)背景色漸變動畫
到今天(2021/04/15),我們還可以使用 CSS @property 實現(xiàn)背景色漸變動畫,它的出現(xiàn),極大的增強的 CSS 的能力!
根據(jù) MDN -- CSS Property[6],@property CSS at-rule 是 CSS Houdini API 的一部分, 它允許開發(fā)者顯式地定義他們的 CSS 自定義屬性,允許進(jìn)行屬性類型檢查、設(shè)定默認(rèn)值以及定義該自定義屬性是否可以被繼承。
- @property --colorA {
- syntax: '<color>';
- inherits: false;
- initial-value: fuchsia;
- }
- @property --colorC {
- syntax: '<color>';
- inherits: false;
- initial-value: #f79188;
- }
- @property --colorF {
- syntax: '<color>';
- inherits: false;
- initial-value: red;
- }
- div {
- background: linear-gradient(45deg,
- var(--colorA),
- var(--colorC),
- var(--colorF));
- animation: change 10s infinite linear;
- }
- @keyframes change {
- 20% {
- --colorA: red;
- --colorC: #a93ee0;
- --colorF: fuchsia;
- }
- 40% {
- --colorA: #ff3c41;
- --colorC: #e228a0;
- --colorF: #2e4c96;
- }
- 60% {
- --colorA: orange;
- --colorC: green;
- --colorF: teal;
- }
- 80% {
- --colorA: #ae63e4;
- --colorC: #0ebeff;
- --colorF: #efc371;
- }
- }
看看效果,完美:
使用 CSS @property 實現(xiàn)的漸變背景動畫
簡單解讀下,CSS @property 其實就是靈活度更高的 CSS 自定義屬性,我們也可以稱其為 CSS Houdini 自定義屬性。其中:
- @property --property-name 中的 --property-name 就是自定義屬性的名稱,定義后可在 CSS 中通過 var(--property-name) 進(jìn)行引用
- syntax:該自定義屬性的語法規(guī)則,也可以理解為表示定義的自定義屬性的類型
- inherits:是否允許繼承
- initial-value:初始值
在上述的 DEMO 中,我們利用了 CSS Houdini 自定義屬性,將原本定義在 background 的過渡效果嫁接到了 color 之上,而 CSS 是支持一個顏色變換到另外一個顏色的,這樣,我們巧妙的實現(xiàn)了漸變背景色的過渡動畫。
關(guān)于更多 CSS @property 相關(guān)的內(nèi)容,你可以戳這篇文章詳細(xì)了解 -- CSS @property,讓不可能變可能[7]
完整的代碼可以戳這里:
CodePen Demo -- CSS Houdini 自定義屬性實現(xiàn)漸變色過渡動畫[8]
至此,我們就得到了 4 種不一樣的,使用純 CSS 制作的漸變背景的過渡動畫的方式。
最后
好了,本文到此結(jié)束,希望對你有幫助 :)
更多精彩 CSS 技術(shù)文章匯總在我的 Github -- iCSS[9] ,持續(xù)更新。
參考資料
[1]CodePen Demo - linear-graident 變換的動畫效果:
https://codepen.io/Chokcoco/pen/VpXEpz
[2]哪些 CSS 屬性可以動畫?:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties
[3]CodePen--Demo--position-size 實現(xiàn)漸變動畫:
https://codepen.io/Chokcoco/pen/KWoYaQ
[4]CodePen--Demo--偽元素配合transform實現(xiàn)背景漸變:
https://codepen.io/Chokcoco/pen/vxRwep
[5]CodePen Demo -- hue-rotate實現(xiàn)漸變背景動畫:
https://codepen.io/Chokcoco/pen/MRegJW
[6]MDN -- CSS Property:
https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property
[7]CSS @property,讓不可能變可能:
https://juejin.cn/post/6951201528543707150
[8]CodePen Demo -- CSS Houdini 自定義屬性實現(xiàn)漸變色過渡動畫:
https://codepen.io/Chokcoco/pen/Bapmzbd
[9]Github -- iCSS:
https://github.com/chokcoco/iCSS