专栏首页鱼头的Web海洋深藏在CSS里的诗情画意(十个原创的CSS特效,不容错过)

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

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

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

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

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

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

洋溢着青春的活力

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

效果地址: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" 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

代码如下:

  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

代码如下:

  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/,通过这个网站就可以自动生成你想要的布局。

代码如下:

  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

代码如下:

  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

代码如下:

  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:

  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轴的移动。

完整代码如下:

  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海洋 ”,随时与鱼头互动。欢迎!衷心希望可以遇见你。

本文分享自微信公众号 - 鱼头的Web海洋(krissarea),作者:陈大鱼头

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Hello CSS】第六章-文档流与排版

    正常流的盒子属于格式化上下文(FC),在CSS2.2中可以是表格、块或内联。 在CSS3中引入了flex跟grid,当然以后会引入得更多。

    陈大鱼头
  • 面试官:你可以用纯 CSS 判断鼠标进入的方向吗?

    在之前某一个前端技术群里,有一个群友说他面试的时候遇到了一个问题,就是面试官让他用纯 CSS 来实现一个根据鼠标移动位置觉得物体移动方向的 DEMO。

    陈大鱼头
  • 我和我亲爱的祖国(用CSS来为祖国母亲庆生)

    相信大家最近已经被 《我和我的祖国》 这首歌给刷屏了,鱼头每次在听到这首歌的时候,总会感慨万千,我们伟大的新中国,这70年真的经历了太多太多了。

    陈大鱼头
  • css3实现ae动画冰激淋流动的遮罩效果

    See the Pen DcHup by Elton Mesquita (@eltonmesquita) on CodePen.1

    Javanx
  • 过渡与变形的综合运用

    王凡汎
  • CSS3 3d环境实现立体 魔方效果代码

              section{width: 100px;height:100px;border:5px solid red; margin:50px au...

    py3study
  • 使用easydrag实现可拖动的DIV弹出框

    最近在工作中遇到了jquery的easydrag插件,我有一种相见恨晚的赶脚!easydrag极大的方法我们实现div弹框这个...

    业余草
  • 3d魔方

    河湾欢儿
  • 九宫格抽奖

    wade
  • css菜鸡的自我救赎0. 前言1. 一些实践方案深入浅出2. 开始试试水

    我们看百度搜索的顶部,顶部的#head(搜索框这一行都是)是fixed的,紧接着的那个div是一个tab。当然fixed脱离文本流,就用padding把自己的主...

    lhyt

扫码关注云+社区

领取腾讯云代金券