我们先来看看实现的效果吧



非常的美腻,对吧。这个是纯css,且单标签实现的哦~

先贴完整代码,我们再来看看这个里面究竟有什么可以借鉴的知识点

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>单标签!纯CSS实现动态晴阴雨雪</title>
  6. </head>
  7. <body>
  8. <div class="weather sunny"></div>
  9. <div class="weather cloudy"></div>
  10. <div class="weather rainy"></div>
  11. <div class="weather snowy"></div>
  12. </body>
  13. <style>
  14. .weather {
  15. position: relative;
  16. display: inline-block;
  17. width: 180px;
  18. height: 240px;
  19. background: #23b7e5;
  20. border-radius: 8px;
  21. }
  22. .sunny:before {
  23. content: "";
  24. position: absolute;
  25. top: 50%;
  26. left: 50%;
  27. transform: translate(-50%, -50%);
  28. width: 60px;
  29. height: 60px;
  30. background: #F6D963;
  31. border-radius: 50%;
  32. box-shadow: 0 0 20px #ff0;
  33. z-index: 2;
  34. }
  35. .sunny:after {
  36. content: "";
  37. position: absolute;
  38. top: 50%;
  39. left: 50%;
  40. margin: -45px 0 0 -45px;
  41. width: 90px;
  42. height: 90px;
  43. background: #FFEB3B;
  44. clip-path: polygon(
  45. 50% 0%,
  46. 65.43% 25%,
  47. 93.3% 25%,
  48. 78.87% 50%,
  49. 93.3% 75%,
  50. 64.43% 75%,
  51. 50% 100%,
  52. 35.57% 75%,
  53. 6.7% 75%,
  54. 21.13% 50%,
  55. 6.7% 25%,
  56. 35.57% 25%);
  57. z-index: 1;
  58. animation: sunScale 2s linear infinite;
  59. }
  60. @keyframes sunScale {
  61. 0% {
  62. transform: scale(1);
  63. }
  64. 50% {
  65. transform: scale(1.1);
  66. }
  67. 100% {
  68. transform: scale(1);
  69. }
  70. }
  71. .cloudy:before,
  72. .rainy:before,
  73. .snowy:before {
  74. content: "";
  75. position: absolute;
  76. top: 50%;
  77. left: 25%;
  78. transform: translate(-50%, -50%);
  79. width: 36px;
  80. height: 36px;
  81. background: #fff;
  82. border-radius: 50%;
  83. box-shadow:
  84. #fff 22px -15px 0 6px,
  85. #fff 57px -6px 0 2px,
  86. #fff 87px 4px 0 -4px,
  87. #fff 33px 6px 0 6px,
  88. #fff 61px 6px 0 2px,
  89. #ccc 29px -23px 0 6px,
  90. #ccc 64px -14px 0 2px,
  91. #ccc 94px -4px 0 -4px;
  92. z-index: 2;
  93. }
  94. .cloudy:before {
  95. animation: cloudMove 2s linear infinite;
  96. }
  97. @keyframes cloudMove {
  98. 0% {
  99. transform: translate(-50%, -50%);
  100. }
  101. 50% {
  102. transform: translate(-50%, -60%);
  103. }
  104. 100% {
  105. transform: translate(-50%, -50%);
  106. }
  107. }
  108. .rainy:after {
  109. content: "";
  110. position: absolute;
  111. top:50%;
  112. left: 25%;
  113. width: 4px;
  114. height: 14px;
  115. background: #fff;
  116. border-radius: 2px;
  117. box-shadow:
  118. #fff 25px -10px 0,
  119. #fff 50px 0 0,
  120. #fff 75px -10px 0,
  121. #fff 0 25px 0,
  122. #fff 25px 15px 0,
  123. #fff 50px 25px 0,
  124. #fff 75px 15px 0,
  125. #fff 0 50px 0,
  126. #fff 25px 40px 0,
  127. #fff 50px 50px 0,
  128. #fff 75px 40px 0;
  129. animation: rainDrop 2s linear infinite;
  130. }
  131. @keyframes rainDrop {
  132. 0% {
  133. transform: translate(0, 0) rotate(10deg);
  134. }
  135. 100% {
  136. transform: translate(-4px, 24px) rotate(10deg);
  137. box-shadow:
  138. #fff 25px -10px 0,
  139. #fff 50px 0 0,
  140. #fff 75px -10px 0,
  141. #fff 0 25px 0,
  142. #fff 25px 15px 0,
  143. #fff 50px 25px 0,
  144. #fff 75px 15px 0,
  145. rgba(255, 255, 255, 0) 0 50px 0,
  146. rgba(255, 255, 255, 0) 25px 40px 0,
  147. rgba(255, 255, 255, 0) 50px 50px 0,
  148. rgba(255, 255, 255, 0) 75px 40px 0;
  149. }
  150. }
  151. .snowy:after {
  152. content: "";
  153. position: absolute;
  154. top:50%;
  155. left: 25%;
  156. width: 8px;
  157. height: 8px;
  158. background: #fff;
  159. border-radius: 50%;
  160. box-shadow:
  161. #fff 25px -10px 0,
  162. #fff 50px 0 0,
  163. #fff 75px -10px 0,
  164. #fff 0 25px 0,
  165. #fff 25px 15px 0,
  166. #fff 50px 25px 0,
  167. #fff 75px 15px 0,
  168. #fff 0 50px 0,
  169. #fff 25px 40px 0,
  170. #fff 50px 50px 0,
  171. #fff 75px 40px 0;
  172. animation: snowDrop 2s linear infinite;
  173. }
  174. @keyframes snowDrop {
  175. 0% {
  176. transform: translateY(0);
  177. }
  178. 100% {
  179. transform: translateY(25px);
  180. box-shadow:
  181. #fff 25px -10px 0,
  182. #fff 50px 0 0,
  183. #fff 75px -10px 0,
  184. #fff 0 25px 0,
  185. #fff 25px 15px 0,
  186. #fff 50px 25px 0,
  187. #fff 75px 15px 0,
  188. rgba(255, 255, 255, 0) 0 50px 0,
  189. rgba(255, 255, 255, 0) 25px 40px 0,
  190. rgba(255, 255, 255, 0) 50px 50px 0,
  191. rgba(255, 255, 255, 0) 75px 40px 0;
  192. }
  193. }
  194. </style>
  195. </html>

我们来看看每一部分的方法

一:晴天图标由两个元素组成:太阳和内六角形阳光。

:before、:after 两个伪类可以在元素内部分别“添加”一个元素,正好都利用上了。

绘制太阳

首先,用 :before实现太阳。

  1. .sunny:before {
  2. content: "";
  3. position: absolute;
  4. top: 50%;
  5. left: 50%;
  6. transform: translate(-50%, -50%);
  7. width: 60px;
  8. height: 60px;
  9. background: #F6D963;
  10. border-radius: 50%;
  11. box-shadow: 0 0 20px #ff0;
  12. z-index: 2;
  13. }

复制代码content用来生成一个元素。

position、top、left、transform用来实现中心居中。

box-shadow实现外发光效果,这只是box-shadow最基本最常用的使用方式

用 :after实现内六角形。

实现的关键就是使用遮罩。通过clip-path绘制一个内六角形。这就变成了一个简单的初中几何问题。

内六角形由两个等边三角形拼合而成。

使用clip-path的polygon方法绘制内六角形,坐标已通过上面的步骤计算出来了。

  1. .sunny:after {
  2. content: "";
  3. position: absolute;
  4. top: 50%;
  5. left: 50%;
  6. margin: -45px 0 0 -45px;
  7. width: 90px;
  8. height: 90px;
  9. background: #FFEB3B;
  10. clip-path: polygon(
  11. 50% 0%,
  12. 65.43% 25%,
  13. 93.3% 25%,
  14. 78.87% 50%,
  15. 93.3% 75%,
  16. 64.43% 75%,
  17. 50% 100%,
  18. 35.57% 75%,
  19. 6.7% 75%,
  20. 21.13% 50%,
  21. 6.7% 25%,
  22. 35.57% 25%);
  23. z-index: 1;
  24. animation: sunScale 2s linear infinite;
  25. }
  26. @keyframes sunScale {
  27. 0% {
  28. transform: scale(1);
  29. }
  30. 50% {
  31. transform: scale(1.1);
  32. }
  33. 100% {
  34. transform: scale(1);
  35. }
  36. }

※注:safari需要将clip-path改为-webkit-clip-path。

实现原理就是通过clip-path绘制了一个内六角形遮罩,把黄颜色背景通过遮罩变成了最终的内六角形。

animation通过关键帧动画实现了“放大缩小”交替动效

阴天

观察图形发现,有两个云朵:前面的白云和后面的乌云。貌似需要分别用 :before和 :after实现。如果这样做的话,后续章节的雨天和雪天的雨雪元素就没有多余的伪类可用了。所以只能用一个伪类实现两朵云。 这里就用到了box-shadow的“影分身”了!

由于后续章节的雨天和雪天都复用了云的样式,所以写在一起了,代码如下:

  1. .cloudy:before,
  2. .rainy:before,
  3. .snowy:before {
  4. content: "";
  5. position: absolute;
  6. top: 50%;
  7. left: 25%;
  8. transform: translate(-50%, -50%);
  9. width: 36px;
  10. height: 36px;
  11. background: #fff;
  12. border-radius: 50%;
  13. z-index: 2;
  14. }

真实的元素(真身)就是一个圆。通过box-shodow来把投影作为“分身”。

先来看看box-shadow的属性:

box-shadow: h-shadow v-shadow blur spread color inset;

参数详解:

h-shadow: 阴影的水平偏移量。

v-shadow: 阴影的垂直偏移量。

blur: 模糊距离(就是渐变的距离,设为0就没有渐变)。

spread: 投影的尺寸,通过这个控制“影分身”的大小。

color: 投影颜色,通过这个实现后方的乌云。

inset: 改为内阴影。这里用不到。

复制多个影分身,带全部影分身的完整代码如下:

  1. .cloudy:before,
  2. .rainy:before,
  3. .snowy:before {
  4. content: "";
  5. position: absolute;
  6. top: 50%;
  7. left: 25%;
  8. transform: translate(-50%, -50%);
  9. width: 36px;
  10. height: 36px;
  11. background: #fff;
  12. border-radius: 50%;
  13. box-shadow:
  14. #fff 22px -15px 0 6px,
  15. #fff 57px -6px 0 2px,
  16. #fff 87px 4px 0 -4px,
  17. #fff 33px 6px 0 6px,
  18. #fff 61px 6px 0 2px,
  19. #ccc 29px -23px 0 6px,
  20. #ccc 64px -14px 0 2px,
  21. #ccc 94px -4px 0 -4px;
  22. z-index: 2;
  23. }

五个分身的白圆(#fff),三个分身的灰圆(#ccc)拼成了两朵云。

再给云朵加上“上下浮动”的动效:

  1. .cloudy:before {
  2. animation: cloudMove 2s linear infinite;
  3. }
  4. @keyframes cloudMove {
  5. 0% {
  6. transform: translate(-50%, -50%);
  7. }
  8. 50% {
  9. transform: translate(-50%, -60%);
  10. }
  11. 100% {
  12. transform: translate(-50%, -50%);
  13. }
  14. }

雨天

云朵的代码直接复用第4章的阴天。这里使用 :after 伪类实现雨滴。

先实现一个雨滴(为方便观看,暂时隐藏云朵):

  1. .rainy:after {
  2. content: "";
  3. position: absolute;
  4. top:50%;
  5. left: 25%;
  6. width: 4px;
  7. height: 14px;
  8. background: #fff;
  9. border-radius: 2px;
  10. }

然后通过box-shadow“影分身”:

  1. .rainy:after {
  2. content: "";
  3. position: absolute;
  4. top:50%;
  5. left: 25%;
  6. width: 4px;
  7. height: 14px;
  8. background: #fff;
  9. border-radius: 2px;
  10. box-shadow:
  11. #fff 25px -10px 0,
  12. #fff 50px 0 0,
  13. #fff 75px -10px 0,
  14. #fff 0 25px 0,
  15. #fff 25px 15px 0,
  16. #fff 50px 25px 0,
  17. #fff 75px 15px 0,
  18. #fff 0 50px 0,
  19. #fff 25px 40px 0,
  20. #fff 50px 50px 0,
  21. #fff 75px 40px 0;
  22. }

再加入下雨的移动动效,修改如下:

  1. .rainy:after {
  2. ...(略)
  3. animation: rainDrop 2s linear infinite;
  4. }
  5. @keyframes rainDrop {
  6. 0% {
  7. transform: translate(0, 0) rotate(10deg);
  8. }
  9. 100% {
  10. transform: translate(-4px, 24px) rotate(10deg);
  11. box-shadow:
  12. #fff 25px -10px 0,
  13. #fff 50px 0 0,
  14. #fff 75px -10px 0,
  15. #fff 0 25px 0,
  16. #fff 25px 15px 0,
  17. #fff 50px 25px 0,
  18. #fff 75px 15px 0,
  19. rgba(255, 255, 255, 0) 0 50px 0,
  20. rgba(255, 255, 255, 0) 25px 40px 0,
  21. rgba(255, 255, 255, 0) 50px 50px 0,
  22. rgba(255, 255, 255, 0) 75px 40px 0;
  23. }
  24. }

动画添加了10度的旋转,让雨滴倾斜,以及垂直方向的移动。

这里的关键就是:虽然本质是垂直移动,但为了看上去是“循环”效果,需要将最下面的雨滴进行透明渐变,同时调节X和Y轴的值,让最终位置正好跟初始位置重合,就不会显得“断开”。

我们生成的是三行雨滴,第一行被云朵挡住了,实际能看到的是下面两行。在第一行移动到第二行位置的时候,原第三行已经透明看不见了,正好与初始状态一样,实现了无缝循环拼接。

雪天与雨天的区别就是把雨滴换成圆形,取消旋转角度。 代码如下:

  1. .snowy:after {
  2. content: "";
  3. position: absolute;
  4. top:50%;
  5. left: 25%;
  6. width: 8px;
  7. height: 8px;
  8. background: #fff;
  9. border-radius: 50%;
  10. box-shadow:
  11. #fff 25px -10px 0,
  12. #fff 50px 0 0,
  13. #fff 75px -10px 0,
  14. #fff 0 25px 0,
  15. #fff 25px 15px 0,
  16. #fff 50px 25px 0,
  17. #fff 75px 15px 0,
  18. #fff 0 50px 0,
  19. #fff 25px 40px 0,
  20. #fff 50px 50px 0,
  21. #fff 75px 40px 0;
  22. animation: snowDrop 2s linear infinite;
  23. }
  24. @keyframes snowDrop {
  25. 0% {
  26. transform: translateY(0);
  27. }
  28. 100% {
  29. transform: translateY(25px);
  30. box-shadow:
  31. #fff 25px -10px 0,
  32. #fff 50px 0 0,
  33. #fff 75px -10px 0,
  34. #fff 0 25px 0,
  35. #fff 25px 15px 0,
  36. #fff 50px 25px 0,
  37. #fff 75px 15px 0,
  38. rgba(255, 255, 255, 0) 0 50px 0,
  39. rgba(255, 255, 255, 0) 25px 40px 0,
  40. rgba(255, 255, 255, 0) 50px 50px 0,
  41. rgba(255, 255, 255, 0) 75px 40px 0;
  42. }
  43. }

本文转载自:https://juejin.im/post/5d2716ab5188257b775d35ba

有趣的纯CSS实现动态晴阴雨雪的更多相关文章

  1. 谈谈一些有趣的CSS题目(八)-- 纯CSS的导航栏Tab切换方案

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  2. 谈谈一些有趣的CSS题目(十四)-- 纯 CSS 方式实现 CSS 动画的暂停与播放!

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  3. 纯CSS无hacks的跨游览器多列布局

    利用纯CSS创建一个等高多列的布局并不件易事,本教程将着重分析出现在多列布局的多个问题,然后为大家等来一个简单全游览器通吃的解决方法,不使用图片,脚本,CSS hacks并在最严格的XHTML 规范中 ...

  4. 超强的纯 CSS 鼠标点击拖拽效果

    背景 鼠标拖拽元素移动,算是一个稍微有点点复杂的交互. 而在本文,我们就将打破常规,向大家介绍一种超强的仅仅使用纯 CSS 就能够实现的鼠标点击拖拽效果. 在之前的这篇文章中 -- 不可思议的纯 CS ...

  5. 纯CSS3实现动态火车行驶特效

    上次开完飞机,这次开火车 查看效果:http://hovertree.com/texiao/css3/7/ 效果图: 代码如下: <!DOCTYPE html> <html> ...

  6. CSS布局技巧 -- 纯CSS让子元素的宽度总和决定其父元素的宽度

    使用场景 在移动端屏幕宽度有限的前提下,使用横向滚动的方式展示更多的内容.在这样的需求下,希望父元素作为容器,其宽度可以又横向排列资源的总宽度动态撑开,超过祖父元素的宽度:在不超过祖父元素时,自动继承 ...

  7. 纯CSS滑动效果

    原文地址:Pure CSS Slide Up and Slide Down 示例地址:Pure CSS Slide Demo 原文日期: 2013年08月26日 翻译日期: 2013年08月27日 如 ...

  8. 纯 CSS 实现波浪效果!

    一直以来,使用纯 CSS 实现波浪效果都是十分困难的. 因为实现波浪的曲线需要借助贝塞尔曲线. 而使用纯 CSS 的方式,实现贝塞尔曲线,额,暂时是没有很好的方法. 当然,借助其他力量(SVG.CAN ...

  9. 分享:纯 css 瀑布流 和 js 瀑布流

    分享一次纯 css 瀑布流  和 js 瀑布流 纯 css 写瀑布流 1.multi-columns 方式: 通过 Multi-columns 相关的属性 column-count.column-ga ...

随机推荐

  1. appium + python 自动化调试手机时 UiAutomator exited unexpectedly with code 0, signal null

    放上appium报错图,appium在手机里安装了appium setting 和unlock 软件,输入法也被变成了appium input ,但是就是点不到目标软件,手机也可以被cmd  adb ...

  2. java笔试之参数解析(正则匹配)

    在命令行输入如下命令: xcopy /s c:\ d:\, 各个参数如下: 参数1:命令字xcopy 参数2:字符串/s 参数3:字符串c:\ 参数4: 字符串d:\ 请编写一个参数解析程序,实现将命 ...

  3. ant的build.xml备份

    <?xml version="1.0" encoding="UTF-8" ?> <project default="rerun&qu ...

  4. Python基础知识之2——字典

    字典是什么? 字典是另外一个可变的数据结构,且可存储任意类型对象,比如字符串.数字.列表等.字典是由关键字和值两部分组成,也就是 key 和 value,中间用冒号分隔.这种结构类似于新华字典,字典中 ...

  5. mysql主从复制linux配置(二进制日志文件)

    安装mysql,两台机器一主(192.168.131.153),一从(192.168.131.154) 主机配置 修改主/etc/my.cnf文件 添加 #server_id=153 ###服务器id ...

  6. node web项目结构

  7. golang和python的二进制转换

    1.二进制转换规则 比如13,对13整除2,余数1,整除变为6,依次类推 13/2=6余1 6/2=3余0 3/2=1余1 1/2=0余1 所以最后的结果为1101 2.python def conv ...

  8. webpack新手名词解释……妈妈再也不担心我看不懂webpack官方文档了

    __dirname : 在任何模块文件内部,可以使用__dirname变量获取当前模块文件所在目录的完整绝对路径. path.resolve(): 方法将一系列路径或路径段解析为绝对路径. 语法: p ...

  9. WebService Exceptions

    一. Exception in thread "main" java.lang.ExceptionInInitializerError at com.sun.xml.interna ...

  10. jquery旋转插件rotate参数说明

    具体可见:http://www.jianshu.com/p/b632a1ed6a57