- 作者:陳大魚頭
- github: KRISACHAN
一聲梧葉一聲秋,一點芭蕉一點愁,三更歸夢三更後。
大概是因為入秋的緣故,最近的感慨比較多。
很多的碎碎念都用都用 HTML 跟 CSS 來記錄在我的codepen https://codepen.io/krischan77 之上,眼見積累到了一些了,就選出幾個來與大家一同分享。
(免責聲明:有些效果是我在網上看到覺得好,然後臨摹下來的,創意不是原創,但是代碼是自己手寫的,如果有看到類似的效果,歡迎大家用來作對比。)
洋溢着青春的活力
-
深藏在CSS裡的詩情畫意(十個原創的CSS特效,不容錯過)
這是兩個帶有彈性勢能的彈跳盒,實作的主要思路就是利用
@keyframes
來控制 盒子的
scale
跟
translate
,進而在視覺上達成彈跳的效果。
效果位址:https://codepen.io/krischan77/pen/QXLdzP
具體代碼:
1. <style>
2. html,
3. body,
4. div {
5. margin: 0;
6. padding: 0;
7. }
8. html,
9. body {
10. width: 100%;
11. height: 100%;
12. }
13. .盒子組 {
14. width: 200px;
15. height: 200px;
16. position: absolute;
17. left: 50%;
18. top: 30px;
19. transform: translateX(-50%);
20. }
21. .大盒子 {
22. width: 100px;
23. height: 100px;
24. transform: scale(1, 1) translate(0, 0px);
25. animation: 大盒子跳 1s 0.3s linear infinite;
26. background: #3170a7;
27. margin: 100px auto;
28. }
29. .小盒子 {
30. width: 60px;
31. height: 60px;
32. transform: scale(1, 1) translate(0, 0px);
33. animation: 小盒子跳 1s 0.3s linear infinite;
34. background: #40a070;
35. margin: 0 auto;
36. position: relative;
37. top: -60px;
38. }
39. @keyframes 大盒子跳 {
40. 0% {
41. transform: scale(1, 1) translate(0, 0px);
42. }
43. 15% {
44. transform: scale(1.13, 0.87) translate(0, 0px);
45. }
46. 30% {
47. transform: scale(0.92, 1.08) translate(0, -40px);
48. }
49. 45% {
50. transform: scale(1.05, 0.95) translate(0, 0px);
51. }
52. 60% {
53. transform: scale(0.93, 1.02) translate(0, -20px);
54. }
55. 75% {
56. transform: scale(1, 1) translate(0, 0px);
57. }
58. 100% {
59. transform: scale(1, 1) translate(0, 0px);
60. }
61. }
62. @keyframes 小盒子跳 {
63. 0% {
64. transform: scale(1, 1) translate(0, 0px);
65. }
66. 50% {
67. transform: scale(1, 1) translate(0, 0px);
68. }
69. 60% {
70. transform: scale(1.13, 0.87) translate(0, 0px);
71. }
72. 70% {
73. transform: scale(0.92, 1.08) translate(0, -40px);
74. }
75. 80% {
76. transform: scale(1.05, 0.95) translate(0, 0px);
77. }
78. 90% {
79. transform: scale(0.98, 1.02) translate(0, -20px);
80. }
81. 100% {
82. transform: scale(1, 1) translate(0, 0px);
83. }
84. }
85. </style>
86. <div class="盒子組">
87. <div class="大盒子">
88. <div class="小盒子"></div>
89. </div>
90. </div>
你的手指在哪裡
這是在很久之前一個網友面試時被問到的問題,當時題目是如何用純CSS實作物體根據滑鼠進入盒子的方向移動,一道挺有意思的題目,當時在群裡各位大佬的讨論下,就有了這樣的實作。
實作思路主要是在盒子四個不同的方位定位好子盒子,然後隐藏的同時讓它們稍稍進入父盒子裡一點,那麼再滑鼠劃進去時,就能觸發該方位隐藏的子盒子的
hover
事件,利用這個障眼法進而達到題目的效果。
效果位址:https://codepen.io/krischan77/pen/RzomRX
代碼如下:
1. <style>
2. body {
3. padding: 2em;
4. text-align: center;
5. }
6. .block {
7. position: relative;
8. display: inline-block;
9. overflow:hidden;
10. width: 10em;
11. height: 10em;
12. vertical-align: middle;
13. -webkit-transform: translateZ(0);
14. }
15. .block_hoverer {
16. position: absolute;
17. z-index: 1;
18. width: 100%;
19. height: 100%;
20. opacity: 0;
21. transition: all .3s ease;
22. }
23. .block_hoverer:nth-child(1) {
24. background: red;
25. top:-90%;
26. }
27. .block_hoverer:nth-child(2) {
28. background: lime;
29. top:90%;
30. }
31. .block_hoverer:nth-child(3) {
32. background: orange;
33. left:-90%;
34. }
35. .block_hoverer:nth-child(4) {
36. background: blue;
37. left:90%;
38. }
39. .block_hoverer:hover {
40. opacity:1;
41. top:0;
42. left:0;
43. }
44. .block_content {
45. position: absolute;
46. top: 0;
47. left: 0;
48. width: 100%;
49. height: 100%;
50. text-align: center;
51. line-height: 10em;
52. background: #333;
53. color: #FFF;
54. }
55. </style>
56. <p class="text">從不同方向使滑鼠指針移過下面的内容</p>
57. <p>↓</p>
58. <span>→ </span>
59. <div class="block">
60. <div class="block_hoverer">1</div>
61. <div class="block_hoverer">2</div>
62. <div class="block_hoverer">3</div>
63. <div class="block_hoverer">4</div>
64. <div class="block_content">
65. Hover me!
66. </div>
67. </div>
68. <span> ←</span>
69. <p>↑</p>
摘下星星送給你
這是用純CSS實作的一個評級功能,主要是利用了
label
标簽跟
input
标簽的關聯性,以及 僞類
:hover
跟
:focus
的操作性實作的。
效果位址:https://codepen.io/krischan77/pen/NZevBr
代碼如下:
1. <style>
2. html,
3. body,
4. div {
5. margin: 0;
6. padding: 0;
7. }
8. html,
9. body {
10. width: 100%;
11. height: 100%;
12. }
13. .container1,
14. .container2
15. {
16. font-size: 60px;
17. display: flex;
18. flex-direction: row-reverse;
19. justify-content: center;
20. }
21. .container1 input {
22. opacity: 0;
23. position: absolute;
24. }
25. .container1 label {
26. color: #aaa;
27. text-decoration: none;
28. -webkit-transition: color .4s;
29. -moz-transition: color .4s;
30. -o-transition: color .4s;
31. transition: color .4s;
32. }
33. .container1 label:hover ~ label,
34. .container1 input:focus ~ label,
35. .container1 label:hover {
36. color: #cc163a;
37. cursor: pointer;
38. }
39. .container2 label {
40. cursor: pointer;
41. font-size: 60px;
42. }
43. .container2 input {
44. opacity: 0;
45. position: absolute;
46. }
47. .container2 label:hover ~ label,
48. .container2 label:hover,
49. .container2 input:focus ~ label,
50. .container2 input:checked ~ label {
51. color: #cc163a;
52. }
53. </style>
54. <section class="container1">
55. <input name="star1" id="s1" type="radio" /><label for="s1">☆</label>
56. <input name="star1" id="s2" type="radio" /><label for="s2">☆</label>
57. <input name="star1" id="s3" type="radio" /><label for="s3">☆</label>
58. <input name="star1" id="s4" type="radio" /><label for="s4">☆</label>
59. <input name="star1" id="s5" type="radio" /><label for="s5">☆</label>
60. </section>
61. <section class="container2">
62. <input type="radio" name="star2" id="s6">
63. <label for="s6">☆</label>
64. <input type="radio" name="star2" id="s7">
65. <label for="s7">☆</label>
66. <input type="radio" name="star2" id="s8">
67. <label for="s8">☆</label>
68. <input type="radio" name="star2" id="s9">
69. <label for="s9">☆</label>
70. <input type="radio" name="star2" id="s10">
71. <label for="s10">☆</label>
72. </section>
客官今天要來點兔子嗎?
這是一隻兔子的路徑動畫,實作原理就是利用
animation
來操作 SVG path的
stroke-dashoffset
,進而實作路徑動畫。
效果位址:https://codepen.io/krischan77/pen/mdbQqRm
代碼如下:
滴水,亦能穿石
1. <style>
2. path {
3. stroke-dasharray: 6600;
4. stroke-dashoffset: 6600;
5. animation: dash 4s linear alternate infinite;
6. fill: transparent;
7. }
8. @keyframes dash {
9. to {
10. stroke-dashoffset: 0;
11. fill: #d81e06;
12. }
13. }
14. </style>
15. <svg width="240" height="240" viewBox="0 0 1165 1024" versinotallow="1.1">
16. <path fill="transparent" stroke="#1296db" stroke-width="30" d="M0.000556 865.83469a66.118285 66.118285 0 0 0 65.93308 65.93308 69.08157 69.08157 0 0 0 39.63393-12.593959 222.246337 222.246337 0 0 0 111.123169 49.44981l26.113945 4.444927a232.247423 232.247423 0 0 0-5.370953 47.968168v2.222463h383.189726v-31.299693a123.717128 123.717128 0 0 0-62.043769-50.746247h-98.158799l-21.669018-15.927654 200.762525-50.931452 11.297522 17.594501 30.373666 79.823477 17.224092 52.227889H907.506434v-32.596129a144.83053 144.83053 0 0 0-38.893109-27.780793l-24.076687-11.667932-40.745161-62.969796v-112.790016a1069.375294 1069.375294 0 0 0 126.495207-140.015193l8.334237-0.926026 188.724182-49.635016h0.926026l36.11503-55.561584v-34.448182l-88.528124-97.417978a257.620546 257.620546 0 0 0-84.824019-61.117743l-13.519986-49.820221L944.54749 157.980105l-29.632845-67.414722L825.460495 10.556701A45.745704 45.745704 0 0 0 777.862737 3.889311a44.819678 44.819678 0 0 0-17.409296 13.33478l-7.408211-6.66739a46.30132 46.30132 0 0 0-74.082113 43.708446l60.376922 190.76144 72.785675 64.821849 12.96437 34.448182a371.706999 371.706999 0 0 0-58.710074 68.711159l-7.778622 11.482728-560.245976 107.048652a222.246337 222.246337 0 0 0-166.684753 267.066016c0 3.14849 1.666848 6.29698 2.592874 9.445469A65.377464 65.377464 0 0 0 0.000556 865.83469z" class="path"></path>
17. </svg>
這個動效主要是利用了
animation
來控制不同關鍵幀下的水滴狀态,這裡的滴水動畫要注意的就是水滴下落的形變,以及到地上時引起的漣漪,主要是要盡量貼合實體現象。
效果位址:https://codepen.io/krischan77/pen/pXdBWP
代碼如下:
1. <style>
連結在此:https://codepen.io/krischan77/pen/pXdBWP
2. .water-damage {
3. position: absolute;
4. top: 50%;
5. left: 50%;
6. transform: translate(-50%, -50%);
7. width: 200px;
8. height: 200px;
9. perspective: 600px;
10. transform-style: preserve-3d;
11. }
12. .water-drop {
13. position: absolute;
14. top: 50%;
15. left: 50%;
16. transform: translate(-50%, -50%);
17. z-index: 10;
18. width: 0;
19. height: 0;
20. border: 10px solid #30DFF3;
21. border-radius: 1000px;
22. margin-top: -10px;
23. margin-left: -10px;
24. opacity: 0;
25. transform-style: preserve-3d;
26. transform-origin: 50% 50%;
27. transform: translate(0, -100px) scale(1, 1);
28. animation: water-drop 3000ms cubic-bezier(.56, .18, .92, .69) infinite;
29. }
30. .water-drop::after {
31. content: "";
32. width: 0;
33. height: 0;
34. border-style: solid;
35. border-width: 0 7.5px 13.0px 7.5px;
36. border-color: transparent transparent #30DFF3 transparent;
37. position: absolute;
38. left: 50%;
39. top: -20px;
40. transform: translate(-50%, 0);
41. }
42. @keyframes water-drop {
43. 0% {
44. opacity: 0;
45. z-index: 10;
46. transform: translate(0, -100px) scale(1, 1);
47. }
48. 50% {
49. opacity: 1;
50. z-index: 10;
51. transform: translate(0, 0) scale(0.8, 1.2);
52. }
53. 51% {
54. opacity: 1;
55. z-index: 10;
56. margin-top: -10px;
57. margin-left: -10px;
58. border-width: 10px;
59. transform: rotateX(70deg);
60. animation-timing-function: cubic-bezier(.12, .41, .63, .99);
61. }
62. 100% {
63. opacity: 0;
64. z-index: 1;
65. margin-top: -200px;
66. margin-left: -200px;
67. border-width: 200px;
68. transform: rotateX(70deg);
69. animation-timing-function: cubic-bezier(.12, .41, .63, .99);
70. }
71. }
72. </style>
73. <div class="water-damage">
74. <div class="water-drop"></div>
75. </div>
即使故障,也要保持優雅
這是因為抖音而走紅的故障風效果,實作原理就是通過
animation
來用
clip-path:inset
對元素進行不同位置的切割,進而實作故障風動畫。
效果位址:https://codepen.io/krischan77/pen/QWLRjpN
代碼如下:
連結在此:https://codepen.io/krischan77/pen/QWLRjpN
1. <style>
2. .glitch-effect {
3. margin: auto;
4. display: flex;
5. justify-content: center;
6. align-items: center;
7. flex-direction: column;
8. position: absolute;
9. top: 10px;
10. left: 0;
11. right: 0;
12. color: #FFF;
13. text-align: center;
14. font-size: 50px;
15. letter-spacing: 10px;
16. }
17. .ge-text {
18. position: relative;
19. color: #fff;
20. font-size: 72px;
21. line-height: 1;
22. letter-spacing: 0.01em;
23. transform: scale3d(1, 1, 1);
24. padding: 10px 50px;
25. background-image: linear-gradient( 135deg, #72EDF2 10%, #5151E5 100%);
26. overflow: hidden;
27. }
28. .ge-text::before, .ge-text::after {
29. content: attr(aria-title);
30. position: absolute;
31. left: 0;
32. top: 0;
33. width: 100%;
34. height: 100%;
35. color: #fff;
36. background-image: linear-gradient( 135deg, #72EDF2 10%, #5151E5 100%);
37. clip-path: inset(79px 50px 43px 0px);
38. overflow: hidden;
39. }
40. .ge-text::before {
41. left: 7px;
42. text-shadow: 1px 0 #a1ffce;
43. animation: glitch-effect 3s infinite linear alternate-reverse;
44. }
45. .ge-text::after {
46. left: 3px;
47. text-shadow: -1px 0 #faffd1;
48. animation: glitch-effect 2s infinite linear alternate-reverse;
49. }
50. @keyframes glitch-effect {
51. 0% {
52. clip-path: inset(4px 50px 61px 0px);
53. }
54. 5% {
55. clip-path: inset(99px 50px 30px 0px);
56. }
57. 10% {
58. clip-path: inset(100px 50px 90px 0px);
59. }
60. 15% {
61. clip-path: inset(69px 50px 98px 0px);
62. }
63. 20% {
64. clip-path: inset(51px 50px 18px 0px);
65. }
66. 25% {
67. clip-path: inset(43px 50px 38px 0px);
68. }
69. 30% {
70. clip-path: inset(67px 50px 71px 0px);
71. }
72. 35% {
73. clip-path: inset(32px 50px 44px 0px);
74. }
75. 40% {
76. clip-path: inset(98px 50px 96px 0px);
77. }
78. 45% {
79. clip-path: inset(92px 50px 93px 0px);
80. }
81. 50% {
82. clip-path: inset(23px 50px 84px 0px);
83. }
84. 55% {
85. clip-path: inset(15px 50px 46px 0px);
86. }
87. 60% {
88. clip-path: inset(53px 50px 9px 0px);
89. }
90. 65% {
91. clip-path: inset(89px 50px 21px 0px);
92. }
93. 70% {
94. clip-path: inset(47px 50px 1px 0px);
95. }
96. 75% {
97. clip-path: inset(98px 50px 55px 0px);
98. }
99. 80% {
100. clip-path: inset(86px 50px 81px 0px);
101. }
102. 85% {
103. clip-path: inset(25px 50px 47px 0px);
104. }
105. 90% {
106. clip-path: inset(49px 50px 87px 0px);
107. }
108. 95% {
109. clip-path: inset(7px 50px 59px 0px);
110. }
111. 100% {
112. clip-path: inset(79px 50px 43px 0px);
113. }
114. }
115. </style>
116. <div class="glitch-effect">
117. <h1 class="ge-text" aria-title="有趣的CSS">AWESOME</h1>
118. </div>
願我如星君如月,夜夜流光相皎潔
這是用
display:grid
完成的心型布局,
grid
真的是一個非常有用布局屬性,建議還不熟的親可以花時間去學習學習,這個心型布局實作的核心就是利用
grid
的二維性來建立一個 columns 為11,rows 為10的盒子,然後按照心型的形狀去定義子元素的
grid-area
,動畫就是正常的顯隐動畫。
效果位址:https://codepen.io/krischan77/pen/wvvWoGy
順便安利下,這是一個線上生成GRID布局的神器:https://cssgrid-generator.netlify.com/,通過這個網站就可以自動生成你想要的布局。
代碼如下:
轉動的時光,能否倒流
1. <style>
2. html,
3. body,
4. div {
5. margin: 0;
6. padding: 0;
7. }
8. html,
9. body {
10. width: 100%;
11. height: 100%;
12. background: linear-gradient(to right, #141e30, #243b55);
13. }
14. .text {
15. text-align: center;
16. line-height: 3;
17. -webkit-text-fill-color: transparent;
18. background: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
19. -webkit-background-clip: text;
20. font-size: 30px;
21. }
22. .parent {
23. width: 700px;
24. height: 700px;
25. display: grid;
26. grid-template-columns: repeat(11, 1fr);
27. grid-template-rows: repeat(10, 1fr);
28. grid-column-gap: 10px;
29. grid-row-gap: 10px;
30. margin: auto;
31. position: absolute;
32. top: 0;
33. right: 0;
34. bottom: 0;
35. left: 0;
36. }
37. .parent > div {
38. background: none;
39. border-radius: 10px;
40. animation-name: love;
41. animation-duration: 0.2s;
42. animation-timing-function: ease;
43. animation-iteration-count: 1;
44. animation-direction: normal;
45. animation-fill-mode: both;
46. animation-play-state: running;
47. }
48. .div1 { grid-area: 3 / 6 / 4 / 7; }
49. .div2 { grid-area: 2 / 7 / 3 / 8; }
50. .div3 { grid-area: 1 / 8 / 2 / 9; }
51. .div4 { grid-area: 1 / 9 / 2 / 10; }
52. .div5 { grid-area: 2 / 10 / 3 / 11; }
53. .div6 { grid-area: 3 / 11 / 4 / 12; }
54. .div7 { grid-area: 4 / 11 / 5 / 12; }
55. .div8 { grid-area: 5 / 11 / 6 / 12; }
56. .div9 { grid-area: 6 / 10 / 7 / 11; }
57. .div10 { grid-area: 7 / 9 / 8 / 10; }
58. .div11 { grid-area: 8 / 8 / 9 / 9; }
59. .div12 { grid-area: 9 / 7 / 10 / 8; }
60. .div13 { grid-area: 10 / 6 / 11 / 7; }
61. .div14 { grid-area: 9 / 5 / 10 / 6; }
62. .div15 { grid-area: 8 / 4 / 9 / 5; }
63. .div16 { grid-area: 7 / 3 / 8 / 4; }
64. .div17 { grid-area: 6 / 2 / 7 / 3; }
65. .div18 { grid-area: 5 / 1 / 6 / 2; }
66. .div19 { grid-area: 4 / 1 / 5 / 2; }
67. .div20 { grid-area: 3 / 1 / 4 / 2; }
68. .div21 { grid-area: 2 / 2 / 3 / 3; }
69. .div22 { grid-area: 1 / 3 / 2 / 4; }
70. .div23 { grid-area: 1 / 4 / 2 / 5; }
71. .div24 { grid-area: 2 / 5 / 3 / 6; }
72. @keyframes love {
73. from {
74. background: none;
75. }
76. to {
77. background: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
78. }
79. }
80. </style>
81. <div class="text">願我如星君如月,夜夜流光相皎潔。</div><div class="parent"><div class="div1"></div><div class="div2"></div><div class="div3"></div><div class="div4"></div><div class="div5"></div><div class="div6"></div><div class="div7"></div><div class="div8"></div><div class="div9"></div><div class="div10"></div><div class="div11"></div><div class="div12"></div><div class="div13"></div><div class="div14"></div><div class="div15"></div><div class="div16"></div><div class="div17"></div><div class="div18"></div><div class="div19"></div><div class="div20"></div><div class="div21"></div><div class="div22"></div><div class="div23"></div><div class="div24"></div></div>
82. <script>
83. 'use strict'
84. const div = [...document.querySelectorAll('.parent > div')]
85. div.forEach((d, i) => {
86. d.style = `animation-delay: ${(i + 1) * 0.2}s`
87. })
88. </script>
這是利用
transform
跟
transition
實作的一個3D輪播圖,就是利用雪碧圖思路将要輪播的背景切割給各個子盒子,然後子盒子進行Z軸變換。
效果位址:https://codepen.io/krischan77/pen/poooxjP
代碼如下:
斯人若彩虹,遇上方知有
1. <style>
2. html,
3. body,
4. div {
5. margin: 0;
6. padding: 0;
7. }
8. html,
9. body {
10. width: 100%;
11. height: 100%;
12. }
13. :root {
14. --base-color: #03A9F4;
15. --bg-color: #3cba92;
16. }
17. .center {
18. position: absolute;
19. margin: auto;
20. top: 50px;
21. right: 0;
22. left: 0;
23. }
24. .box {
25. width: calc(var(--base-size) * 4);
26. height: var(--base-size);
27. }
28. .slider {
29. width: var(--base-size);
30. height: var(--base-size);
31. color: var(--base-color);
32. perspective: 0px;
33. transform-style: preserve-3d;
34. position: absolute;
35. top: 0;
36. transform: rotateX(0deg);
37. }
38. .slider-1 {
39. left: calc(var(--base-size) * 0);
40. transition: all 1s linear 0s;
41. }
42. .slider-2 {
43. left: calc(var(--base-size) * 1);
44. transition: all 1s linear 0.5s;
45. }
46. .slider-3 {
47. left: calc(var(--base-size) * 2);
48. transition: all 1s linear 1s;
49. }
50. .slider-4 {
51. left: calc(var(--base-size) * 3);
52. transition: all 1s linear 1.5s;
53. }
54. .slider-page {
55. transform-style: preserve-3d;
56. width: var(--base-size);
57. height: var(--base-size);
58. position: relative;
59. }
60. .slider-main {
61. width: var(--base-size);
62. height: var(--base-size);
63. position:absolute;
64. box-sizing: border-box;
65. border: 1px solid currentcolor;
66. }
67. .slider-front {
68. transform: translateZ(calc(var(--base-size) / 2));
69. background-image: url(http://www.33lc.com/article/UploadPic/2012-8/2012891154949207.jpg);
70. border: none;
71. }
72. .slider-bottom {
73. transform: rotateX(-90deg) translateZ(calc(var(--base-size) / 2));
74. background-image: url(http://pic1.win4000.com/wallpaper/3/5858a0ab1ceb6.jpg);
75. border: none;
76. }
77. .slider-back {
78. transform: rotateZ(180deg) translateZ(calc(calc(-1 * var(--base-size)) / 2));
79. background-image: url(http://pic1.win4000.com/wallpaper/2/53cf2c1e5056b.jpg);
80. border: none;
81. }
82. .slider-top {
83. transform: rotateX(90deg) translateZ(calc(var(--base-size) / 2));
84. background-image: url(http://img.zcool.cn/community/03886cf575a66110000018c1b51ca27.jpg);
85. border: none;
86. }
87. .slider-right {
88. visibility: hidden;
89. transform: rotateY(90deg) translateZ(calc(var(--base-size) / 2));
90. }
91. .slider-left {
92. visibility: hidden;
93. transform: rotateY(-90deg) translateZ(calc(var(--base-size) / 2));
94. }
95. </style>
96. <div class="box center">
97. <div class="slider slider-1">
98. <div class="slider-page">
99. <div class="slider-main slider-front"></div>
100. <div class="slider-main slider-bottom"></div>
101. <div class="slider-main slider-back"></div>
102. <div class="slider-main slider-top"></div>
103. <div class="slider-main slider-right"></div>
104. <div class="slider-main slider-left"></div>
105. </div>
106. </div>
107. <div class="slider slider-2">
108. <div class="slider-page">
109. <div class="slider-main slider-front"></div>
110. <div class="slider-main slider-bottom"></div>
111. <div class="slider-main slider-back"></div>
112. <div class="slider-main slider-top"></div>
113. <div class="slider-main slider-right"></div>
114. <div class="slider-main slider-left"></div>
115. </div>
116. </div>
117. <div class="slider slider-3">
118. <div class="slider-page">
119. <div class="slider-main slider-front"></div>
120. <div class="slider-main slider-bottom"></div>
121. <div class="slider-main slider-back"></div>
122. <div class="slider-main slider-top"></div>
123. <div class="slider-main slider-right"></div>
124. <div class="slider-main slider-left"></div>
125. </div>
126. </div>
127. <div class="slider slider-4">
128. <div class="slider-page">
129. <div class="slider-main slider-front"></div>
130. <div class="slider-main slider-bottom"></div>
131. <div class="slider-main slider-back"></div>
132. <div class="slider-main slider-top"></div>
133. <div class="slider-main slider-right"></div>
134. <div class="slider-main slider-left"></div>
135. </div>
136. </div>
137. </div>
138. <script>
139. 'use strict'
140. const baseSize = 200
141. document.documentElement.style.setProperty('--base-size', baseSize + 'px')
142. const sliders = [...document.querySelectorAll('.slider')]
143. const len = sliders - 1
144. sliders.forEach((slider, idx) => {
145. const xPos = (idx * baseSize)
146. const front = slider.querySelector('.slider-front')
147. const bottom = slider.querySelector('.slider-bottom')
148. const back = slider.querySelector('.slider-back')
149. const top = slider.querySelector('.slider-top')
150. front.style = `background-position: -${xPos}px -100px;`
151. bottom.style = `background-position: -${xPos}px -100px;`
152. back.style = `background-position: ${xPos}px 0px;`
153. top.style = `background-position: -${xPos}px -100px;`
154. })
155. const setPos = () => {
156. let index = 0
157. const setRotateX = () => {
158. index++
159. if (index > 3) {
160. index = 0
161. }
162. sliders.forEach(slider => {
163. slider.style.transform = `rotateX(${index * 90}deg)`
164. })
165. setTimeout(() => {
166. setRotateX()
167. }, 3000)
168. }
169. setRotateX()
170. }
171. setPos()
172. </script>
這是利用了
cubic-bezier
貝塞爾曲線的特性實作的動畫,彩虹條的顔色是利用了
filter:hue-rotate
去将色調轉換。
效果位址:https://codepen.io/krischan77/pen/OJJVbxJ
代碼如下:
這是線上生成貝塞爾曲線的網站,通過這個網站,你不需要手寫,隻需要線上調試就可以生成需用的值:https://cubic-bezier.com
1. <style>
2. html,
3. body,
4. div {
5. margin: 0;
6. padding: 0;
7. }
8. html,
9. body {
10. background: linear-gradient(to right, #0f2027, #203a43, #2c5364);
11. width: 100%;
12. height: 100%;
13. }
14. h1 {
15. text-align: center;
16. line-height: 3;
17. font-weight: 700;
18. -webkit-text-fill-color: transparent;
19. background-color: hsla(0, 100%, 60%, .8);
20. -webkit-background-clip: text;
21. animation: textColorRotate 5s linear infinite;
22. letter-spacing:2px
23. }
24. .rainbow-box {
25. position: absolute;
26. top: 100px;
27. right: 0;
28. left: 0;
29. margin: auto;
30. width: 200px;
31. height: 200px;
32. }
33. .rainbow-arc {
34. position: absolute;
35. left: 0;
36. top: 0;
37. width: 200px;
38. height: 100px;
39. box-sizing: border-box;
40. overflow: hidden;
41. transform-origin: 50% 100%;
42. animation: rainbowMove 3s cubic-bezier(.58,-0.57,.5,1.66) infinite;
43. }
44. .rainbow-arc-main {
45. border: 4px solid transparent;
46. border-radius: 100%;
47. box-sizing: border-box;
48. height: 150px;
49. left: 0;
50. margin: 0 auto;
51. position: absolute;
52. right: 0;
53. top: 0;
54. width: 150px;
55. }
56. .rainbow-arc:nth-child(1) {
57. animation-delay: -50ms;
58. }
59. .rainbow-arc:nth-child(2) {
60. animation-delay: -100ms;
61. }
62. .rainbow-arc:nth-child(3) {
63. animation-delay: -150ms;
64. }
65. .rainbow-arc:nth-child(4) {
66. animation-delay: -200ms;
67. }
68. .rainbow-arc:nth-child(5) {
69. animation-delay: -250ms;
70. }
71. .rainbow-arc:nth-child(6) {
72. animation-delay: -300ms;
73. }
74. .rainbow-arc:nth-child(7) {
75. animation-delay: -350ms;
76. }
77. .rainbow-arc:nth-child(1) .rainbow-arc-main {
78. border-color: hsla(0, 100%, 60%, .8);
79. height: 200px;
80. width: 200px;
81. top: 10px;
82. }
83. .rainbow-arc:nth-child(2) .rainbow-arc-main {
84. border-color: hsla(30, 100%, 60%, .8);
85. height: 180px;
86. width: 180px;
87. top: 20px;
88. }
89. .rainbow-arc:nth-child(3) .rainbow-arc-main {
90. border-color: hsla(60, 100%, 60%, .8);
91. height: 160px;
92. width: 160px;
93. top: 30px;
94. }
95. .rainbow-arc:nth-child(4) .rainbow-arc-main {
96. border-color: hsla(90, 100%, 60%, .8);
97. height: 140px;
98. width: 140px;
99. top: 40px;
100. }
101. .rainbow-arc:nth-child(5) .rainbow-arc-main {
102. border-color: hsla(120, 100%, 60%, .8);
103. height: 120px;
104. width: 120px;
105. top: 50px;
106. }
107. .rainbow-arc:nth-child(6) .rainbow-arc-main {
108. border-color: hsla(150, 100%, 60%, .8);
109. height: 100px;
110. width: 100px;
111. top: 60px;
112. }
113. .rainbow-arc:nth-child(7) .rainbow-arc-main {
114. border-color: hsla(180, 100%, 60%, .8);
115. height: 80px;
116. width: 80px;
117. top: 70px;
118. }
119. @keyframes textColorRotate {
120. from {
121. filter: hue-rotate(0deg);
122. }
123. to {
124. filter: hue-rotate(360deg);
125. }
126. }
127. @keyframes rainbowMove {
128. 0%, 15% {
129. transform: rotate(0);
130. }
131. 100% {
132. transform: rotate(360deg);
133. }
134. }
135. </style>
136. <h1><i>斯人若彩虹,遇上方知有</i></h1>
137. <div class="rainbow-box">
138. <div class="rainbow-arc">
139. <div class="rainbow-arc-main"></div>
140. </div>
141. <div class="rainbow-arc">
142. <div class="rainbow-arc-main"></div>
143. </div>
144. <div class="rainbow-arc">
145. <div class="rainbow-arc-main"></div>
146. </div>
147. <div class="rainbow-arc">
148. <div class="rainbow-arc-main"></div>
149. </div>
150. <div class="rainbow-arc">
151. <div class="rainbow-arc-main"></div>
152. </div>
153. <div class="rainbow-arc">
154. <div class="rainbow-arc-main"></div>
155. </div>
156. <div class="rainbow-arc">
157. <div class="rainbow-arc-main"></div>
158. </div>
159. </div>
我和我親愛的祖國,一刻也不能分割
效果位址:https://codepen.io/krischan77/pen/WNeqOeB
這個效果是為了慶祝祖國母親70周年生日而畫的,這裡的五星紅旗是通過SVG畫的,早前在自己的文章裡有提過五星紅旗的具體屬性。
國旗是五星紅旗,旗面為紅色,長寬比例為3:2。左上方綴黃色五角星五顆,四顆小星(其外接圓直徑為旗高1/10)環拱在一顆大星(其外接圓直徑為旗高3/10)的右面,并各有一個角尖正對大星的中心點。
通用尺寸有以下五種:
- 長288厘米,高192厘米;
- 長240厘米,高160厘米;
- 長192厘米,高128厘米;
- 長144厘米,高96厘米;
- 長96厘米,高64厘米。
是以我們有以下的墨線圖:
是以按照這個比例我們能畫出這樣的SVG:
至于飄揚的動畫部分,同樣是利用了雪碧圖的原理,将圖檔的每一塊區域指派給dom節點,然後利用
transform
進行Y軸的移動。
1. <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 30 20">
2. <defs>
3. <path id="s" d="M0,-1 0.587785,0.809017 -0.951057,-0.309017H0.951057L-0.587785,0.809017z" fill="#ffde00"/>
4. </defs>
5. <rect width="30" height="20" fill="#de2910"/>
6. <use xlink:href="#s" transform="translate(5,5) scale(3)"/>
7. <use xlink:href="#s" transform="translate(10,2) rotate(23.036243)"/>
8. <use xlink:href="#s" transform="translate(12,4) rotate(45.869898)"/>
9. <use xlink:href="#s" transform="translate(12,7) rotate(69.945396)"/>
10. <use xlink:href="#s" transform="translate(10,9) rotate(20.659808)"/>
11. </svg>
完整代碼如下:
其實CSS還是很有趣的,各位有興趣也可以多多發掘,多多開腦洞來創作一些有趣的特效。
1. <style>
2. * {
3. margin: 0;
4. padding: 0;
5. }
6. html,
7. body {
8. height: 100%;
9. width: 100%;
10. }
11. li {
12. list-style: none;
13. }
14. .flag {
15. position: absolute;
16. left: 50%;
17. top: 50%;
18. animation: wave ease-in-out infinite;
19. }
20. .flag > li {
21. height: 100%;
22. float: left;
23. background-image: url("https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/others/chinese/flag.jpg");
24. background-size: auto 100%;
25. animation: flag ease-in-out infinite;
26. }
27. </style>
28. <ul id="flag" class="flag"></ul>
29. <script>
30. const flag = document.querySelector('#flag')
31. const image = new Image()
32. image.src = 'https://fish-pond-1253945200.cos.ap-guangzhou.myqcloud.com/others/chinese/flag.jpg'
33. const flagWidth = 800
34. const flagHeight = 640
35. let imgWidth = ''
36. let imgHeight = ''
37. const imgRender = ({
38. sliceCount = 70,
39. amplitude = 20,
40. period = 1.5,
41. duration = 2,
42. }) => {
43. const style = document.createElement('style')
44. const styleSplinter = []
45. const sliceCountPerPeriod = Math.floor(sliceCount / period)
46. const sliceWidth = imgWidth / sliceCount
47. const formula = sliceCountPerPeriod + 'n+'
48. const delay = (duration * period / sliceCount)
49. for (let i = 0; i < sliceCount; ++i) {
50. if (i < sliceCountPerPeriod) {
51. styleSplinter.push(`
52. .flag > li:nth-child(${formula + i}) {
53. animation-delay: -${delay * (sliceCountPerPeriod - i)}s;
54. }
55. `)
56. }
57. styleSplinter.push(`
58. .flag > li:nth-child(${i}) {
59. background-position: -${i * sliceWidth}px 0;
60. }
61. `)
62. }
63. styleSplinter.push(`
64. @keyframes flag {
65. 0% { transform: translate3d(0, ${amplitude}px, 0); }
66. 50% { transform: translate3d(0, ${-amplitude}px, 0); }
67. 100% { transform: translate3d(0, ${amplitude}px, 0); }
68. }
69. @keyframes wave {
70. 0% { transform: translate3d(0, ${-amplitude}px, 0); }
71. 50% { transform: translate3d(0, ${amplitude}px, 0); }
72. 100% { transform: translate3d(0, ${-amplitude}px, 0); }
73. }
74. .flag {
75. animation-duration: ${duration}s;
76. animation-delay: -${delay * sliceCountPerPeriod}s;
77. }
78. .flag > li {
79. animation-duration: ${duration}s;
80. width: ${imgWidth / sliceCount}px;
81. }
82. `)
83. style.innerHTML = styleSplinter.join('')
84. flag.innerHTML = new Array(sliceCount + 1).join('<li></li>')
85. document.documentElement.appendChild(style)
86. }
87. image.onload = () => {
88. imgWidth = image.width
89. imgHeight = image.height
90. const ratio = image.width / image.height
91. if (imgWidth > flagWidth) {
92. imgWidth = flagWidth
93. imgHeight = imgWidth / ratio
94. }
95. if (imgHeight > flagHeight) {
96. imgWidth = imgHeight * ratio
97. imgHeight = flagHeight
98. }
99. flag.style.width = imgWidth + 'px'
100. flag.style.height = imgHeight + 'px'
101. flag.style.marginLeft = -imgWidth / 2 + 'px'
102. flag.style.marginTop = -imgHeight / 2 + 'px'
103. imgRender({
104. sliceCount: 70,
105. amplitude: 20,
106. period: 1.5,
107. duration: 2,
108. })
109. }
110. </script>
魚頭我時不時就會上https://codepen.io/去看别人的創意,從中擷取寫CSS的靈感,各位對CSS感興趣,或者希望可以增強CSS水準的都可以進去看看,當然裡面不止有CSS,還有各類DEMO,算是可視化版的github了~