前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深藏在CSS里的诗情画意(十个原创的CSS特效,不容错过)

深藏在CSS里的诗情画意(十个原创的CSS特效,不容错过)

作者头像
陈大鱼头
发布2020-04-16 16:42:38
6790
发布2020-04-16 16:42:38
举报
文章被收录于专栏:鱼头的Web海洋鱼头的Web海洋

  • 作者:陈大鱼头
  • github: KRISACHAN

一声梧叶一声秋,一点芭蕉一点愁,三更归梦三更后。

大概是因为入秋的缘故,最近的感慨比较多。

很多的碎碎念都用都用 HTMLCSS 来记录在我的codepen https://codepen.io/krischan77 之上,眼见积累到了一些了,就选出几个来与大家一同分享。

(免责声明:有些效果是我在网上看到觉得好,然后临摹下来的,创意不是原创,但是代码是自己手写的,如果有看到类似的效果,欢迎大家用来作对比。)

洋溢着青春的活力

这是两个带有弹性势能的弹跳盒,实现的主要思路就是利用 @keyframes 来控制 盒子的 scaletranslate ,从而在视觉上达成弹跳的效果。

效果地址:https://codepen.io/krischan77/pen/QXLdzP

具体代码:

代码语言:javascript
复制
  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

代码如下:

代码语言:javascript
复制
  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

代码如下:

代码语言:javascript
复制
  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

代码如下:

代码语言:javascript
复制
  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" version="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

代码如下:

代码语言:javascript
复制
  1. <style>
  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>

链接在此:https://codepen.io/krischan77/pen/pXdBWP

即使故障,也要保持优雅

这是因为抖音而走红的故障风效果,实现原理就是通过 animation 来用 clip-path:inset 对元素进行不同位置的切割,从而实现故障风动画。

效果地址:https://codepen.io/krischan77/pen/QWLRjpN

代码如下:

代码语言:javascript
复制
  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>

链接在此:https://codepen.io/krischan77/pen/QWLRjpN

愿我如星君如月,夜夜流光相皎洁

这是用 display:grid 完成的心型布局, grid真的是一个非常有用布局属性,建议还不熟的亲可以花时间去学习学习,这个心型布局实现的核心就是利用 grid的二维性来创建一个 columns 为11,rows 为10的盒子,然后按照心型的形状去定义子元素的 grid-area,动画就是常规的显隐动画。

效果地址:https://codepen.io/krischan77/pen/wvvWoGy

顺便安利下,这是一个在线生成GRID布局的神器:https://cssgrid-generator.netlify.com/,通过这个网站就可以自动生成你想要的布局。

代码如下:

代码语言:javascript
复制
  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>

转动的时光,能否倒流

这是利用 transformtransition 实现的一个3D轮播图,就是利用雪碧图思路将要轮播的背景切割给各个子盒子,然后子盒子进行Z轴变换。

效果地址:https://codepen.io/krischan77/pen/poooxjP

代码如下:

代码语言:javascript
复制
  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

代码如下:

代码语言:javascript
复制
  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://cubic-bezier.com

我和我亲爱的祖国,一刻也不能分割

效果地址:https://codepen.io/krischan77/pen/WNeqOeB

这个效果是为了庆祝祖国母亲70周年生日而画的,这里的五星红旗是通过SVG画的,早前在自己的文章里有提过五星红旗的具体属性。

国旗是五星红旗,旗面为红色,长宽比例为3:2。左上方缀黄色五角星五颗,四颗小星(其外接圆直径为旗高1/10)环拱在一颗大星(其外接圆直径为旗高3/10)的右面,并各有一个角尖正对大星的中心点。

通用尺寸有以下五种:

  1. 长288厘米,高192厘米;
  2. 长240厘米,高160厘米;
  3. 长192厘米,高128厘米;
  4. 长144厘米,高96厘米;
  5. 长96厘米,高64厘米。

所以我们有以下的墨线图:

所以按照这个比例我们能画出这样的SVG:

代码语言:javascript
复制
  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>

至于飘扬的动画部分,同样是利用了雪碧图的原理,将图片的每一块区域赋值给dom节点,然后利用 transform 进行Y轴的移动。

完整代码如下:

代码语言:javascript
复制
  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>

其实CSS还是很有趣的,各位有兴趣也可以多多发掘,多多开脑洞来创作一些有趣的特效。

鱼头我时不时就会上https://codepen.io/去看别人的创意,从中获取写CSS的灵感,各位对CSS感兴趣,或者希望可以增强CSS水平的都可以进去看看,当然里面不止有CSS,还有各类DEMO,算是可视化版的github了~

如果你、喜欢探讨技术,或者对本文有任何的意见或建议,你可以扫描下方二维码,关注微信公众号“ 鱼头的Web海洋 ”,随时与鱼头互动。欢迎!衷心希望可以遇见你。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鱼头的Web海洋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 洋溢着青春的活力
  • 你的手指在哪里
  • 摘下星星送给你
  • 客官今天要来点兔子吗?
  • 滴水,亦能穿石
  • 即使故障,也要保持优雅
  • 愿我如星君如月,夜夜流光相皎洁
  • 转动的时光,能否倒流
  • 斯人若彩虹,遇上方知有
  • 我和我亲爱的祖国,一刻也不能分割
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档