CSS优秀起来真没JS什么事

论坛 期权论坛 期权     
妙味前端   2019-7-8 06:26   2784   0
原文:https://css-tricks.com/state-css-reflections/
说明:为方便读者理解,本文采用意译,非直译;其次,原文极长,作者还给出了浏览器兼容方案,本译文重点介绍
  1. box-reflex
复制代码
属性的作用效果,不阐述兼容问题,有兴趣的读者可以点击原文阅读,谢谢~
最后:翻译不易,译文求Star: //github.com/qiud...
最近我在CodePen上发现了一个纯CSS实现,具有渐变倒影和3D旋转效果的栅栏动画,他的实现方式是:利用10个
  1. [/code]元素创建10个栅条,接着再复制整份[code]
复制代码
元素,并创建一个渐变遮罩形成渐变效果,以此作为栅栏的倒影。

这听起来有点像用左脚的脚趾去抓你的右耳背部(译者理解:表达的意思应该是用了复杂的方式去处理一个其实可以用简单方式达成的事情)!更不用说这种渐变遮罩的方式根本不适用于非单一颜色的背景。难道没有基于CSS的更好的方法吗?





答案是有的,我们有更好的方式可以实现这种效果!但遗憾的是,这种方式的兼容性不够好,如果我们不想使用
  1. canvas
复制代码
,但又希望能够兼容所有的主浏览器,上述的方法无疑还是最好的。

本文将探讨今天我们创建倒影的所有可行选择,阐述这些“相似”的解决方案,在跨浏览器问题上导致的痛苦,最后就这些问题该怎么做讨论下我的想法(译文没这么多内容)。

基础代码
[h1][/h1]在讨论倒影之前,我们先看看如何创建、定位和着色栅栏条,因为这部分对所有的浏览器都是通用的。

首先我们创建了一个
  1. .loader
复制代码
包装器并包含10个
  1. .bar
复制代码
元素
  1. [/code][code]   
复制代码
  1. [/code]除了直接写HTML外,我们也可以用预处理器,比如Haml:
  2. [code].loader  - 10.times do  .bar
复制代码
  1. [/code]我们从视口的中间位置开始定位这些元素。通常我们都是使用[code]top: 50%
复制代码
去居中,但如果我们用
  1. bottom: 50%
复制代码
后面会更方便。
  1. [/code][code]div {  position: absolute;  bottom: 50%; left: 50%;}
复制代码
  1. [/code]我们给这些栅栏条定义宽度和高度,
  2. 同时给它一个背景:
  3. [code]
复制代码
  1. $bar-w: 1.25em;$bar-h: 5 * $bar-w;.bar {  width: $bar-w; height: $bar-h;  background: currentColor;}
复制代码
  1. [/code]我们希望栅条的底部边缘可以跟视口的横向中轴线相重叠,通过前面我们设置[code]bottom: 50%
复制代码
已经实现了这种效果。此时,我们所有栅条是全部堆叠在一起的,他们的左边缘与视口的纵向中轴线重合,底部边缘则与横向中轴线重叠,在线查看:





定位栅栏
[h1][/h1]我们需要将这些栅栏定位为:第一条栅条左边缘和最后一条栅条右边缘与纵向中轴线之间的距离相同,这个距离总是等于条数(
  1. $n
复制代码
)乘以条宽(
  1. $bar-w
复制代码
)结果值的一半。最初的演示用的是普通的
  1. CSS
复制代码
,现在我们使用
  1. Sass
复制代码
来简化代码量,这里查看:




译者:特别提醒,条宽
  1. $bar-w
复制代码
中间是连接符,不是减号,避免引起歧义,后续使用
  1. $bar_w
复制代码
替代



这意味着,从所有栅条的位置开始,我们需要把第一个栅条向左移动
  1. 0.5 * $n * $bar_w
复制代码
。左边是
  1. x
复制代码
轴的负方向,这意味着前面需要加一个负号,因此第一个栅条的
  1. margin-left
复制代码
值是
  1. -.5 * $n * $bar_w
复制代码


第二个栅条的位置则是在第一个栅条位置上往右移动一个栅条宽度的距离,那么它的
  1. margin-left
复制代码
值应该是
  1. -.5 * $n * $bar_w + $bar_w
复制代码
;

同理第三个栅条的
  1. margin-left
复制代码
值为
  1. -.5 * $n * $bar_w + 2 * $bar_w
复制代码
;

那么最后一个栅条的
  1. margin-left
复制代码
就是:
  1. -.5 * $n * $bar-w + ($n - 1) * $bar-w
复制代码
.
如下图:在线查看



我们用代码表述为:
  1. [/code][code]$n: 10;@for $i from 0 to $n {  .bar:nth-child(#{$i + 1}) {  margin-left: ($i - .5 * $n) * $bar-w;  }}
复制代码
  1. [/code]我们给它们设置下[code]box-shadow
复制代码
,这样我们可以清楚地
看到一个栅条的结束和下一个栅条的开始:




给栅栏上色

[h1]栅栏的背景颜色从最左边的深蓝色
  1. #1e3f57
复制代码
)过度到最右边的浅蓝色
  1. #63a6c1
复制代码
),这听起来像是
  1. Sass
复制代码
  1. mix()
复制代码
函数做的事情。
  1. mix()
复制代码
的第一个参数是淡蓝色,第二个参数是深蓝色,第三个参数(称为相对权重,以%为单位)是最终混合结果中淡蓝色包含的量。[/h1]
对于第一个栅条,淡蓝色的量应该为
  1. 0% - 0%
复制代码
,因此最终结果仅为深蓝色;

相同地,对于最后一个栅条,淡蓝色的量应该为
  1. 100% -100%
复制代码
,背景色的构成就是淡蓝色;

对于剩下的栅条,我们需要让中间值均匀分布。假设我们有
  1. $n
复制代码
个栅条,第一个是
  1. 0%
复制代码
,最后一个是
  1. 100%
复制代码
,然后我们需要把它们分成
  1. $n - 1
复制代码
个等距间隔。如下图:


一般来说,编号
  1. $i
复制代码
的栅条的相对权重为:
  1. $i * 100% / ($n - 1)
复制代码
,我们添加如下代码:
  1. $c: #63a6c1 #1e3f57; // 1st = light 2nd = dark@for $i from 0 to $n {  // list of mix() arguments for current bar  $args: append($c, $i * 100% / ($n - 1));  .bar:nth-child(#{$i + 1}) {  background: mix($args...);  }}
复制代码
  1. [/code]现在,这些栅栏看起来跟最初演示的一样:在线查看
  2. [img]https://201907.oss-cn-shanghai.aliyuncs.com/wc/1811847-f3845621d09ace0ae94dc87244f6cfeb[/img]
  3. -webkit-box-reflect
  4. [h1][/h1][code]box-reflect
复制代码
仍然是一个非标准属性,许多主流浏览器尚未对其进行支持,幸运的是,它可以在
  1. webkit
复制代码
浏览器中很好地运行,只需要加上浏览器的私有属性就可以了。

让我们看一下它是怎么工作的,他的值有三部分:
  1. -webkit-box-reflect:none |  ? ?
复制代码
    1. [/code][/b]:倒影的方向,可以是[code]below
    复制代码
    ,
    1. left
    复制代码
    ,
    1. above
    复制代码
    ,
    1. right
    复制代码
    中的任意值
    1. [/code][/b]:倒影与原像的距离,取值可以是固定像素值或百分比
    2. [*][b][code]
    复制代码
    :设置倒影的遮罩效果,可以是背景图片或渐变图像

下面的交互demo阐述了这点(可以点击更改倒影的方向、偏移量等):
直接访问demo自个玩吧!
在我们的例子中,首先想到的是在
  1. .loader
复制代码
中添加这个:
  1. [/code][code].loader {  -webkit-box-reflect: below 0 linear-gradient(rgba(#fff, 0), rgba(#fff, .7));}
复制代码
其次我们还需要给
  1. .loader
复制代码
设置尺寸,因为它包含的栅栏都是绝对定位的,此时
  1. .loader
复制代码
的实际尺寸是
  1. 0px X 0px
复制代码
。我们将其宽度定义为所有栅栏宽度之和,高度则与栅栏高度一致:
  1. [/code][code]$loader-w: $n * $bar-w;.loader {  width: $loader-w; height: $bar-h;  box-shadow: 0 0 0 1px red;}
复制代码
  1. [/code]添加上面的代码后,
  2. 在webkit浏览器中会看到下面的效果:在线查看
  3. [img]https://201907.oss-cn-shanghai.aliyuncs.com/wc/1811847-3993db58b535aaf3ca7a9b163da60baf[/img]
  4. 我们已经可以看到加载器的边界和一些倒影,但它们的位置不再正确了。我们需要将加载器左移居中,同时让栅栏底部与它们父元素的底部重合:
  5. [code]
复制代码
  1. .loader { margin-left: -.5 * $loader-w; }.bar { bottom: 0; }
复制代码
这样就解决了定位的问题,效果如:




// 这里省略一堆关于Firefox的兼容方案:element()+svg的mask ......
动画
[h1][/h1]最初在CodePen实现的动画非常简单,只是一个3D旋转栅栏:
  1. @keyframes bar {  0% {  transform: rotate(-.5turn) rotateX(-1turn);  }  75%, 100% { transform: none; }}
复制代码
  1. [/code]将动画应用在所有的栅栏上:
  2. [code]
复制代码
  1. animation: bar 3s cubic-bezier(.81, .04, .4, .7) infinite;
复制代码
  1. [/code]接着为每个栅条添加不同的延时:
  2. [code]
复制代码
  1. animation-delay: $i*50ms;
复制代码
  1. [/code]
  2. 由于我们是3D旋转栅栏,
  3. 因此我们还需要在loader元素上
  4. 添加perspective属性:
  5. [code]
复制代码
  1. [/code][code].loader {  perspective: 62.5em;}
复制代码
但这只在webkit浏览器中使用-webkit-box-reflect时有效。最终实现的效果:在线查看




最后一点思考
[h1][/h1]算了,这段不用翻译了!

大意讲作者对
  1. -webkit-box-reflect
复制代码
  1. element()+mask
复制代码
  1. svg
复制代码
  1. mask
复制代码
标签)解决跨浏览器实现倒影问题上的看法,不影响我们理解
  1. box-reflect
复制代码
的优秀,有兴趣的读者可以去看看原文,感恩~
作者:_安歌链接:https://juejin.im/post/5d148f64f265da1bae390ce3



尤雨溪:Vue Function-based API RFC

Vue+Node+高德地图+Echart做一款出行可视化全栈webapp
2019前端面试基础题集合!赶紧上车!

[译]Vue 最黑暗的一天




感谢阅读,如果觉得还不错,欢迎多多转发点赞,推荐给更多的小伙伴哟




更多前端系统学习视频教程,点击这里获取哦:https://study.miaov.com/study

好消息~好消息~即日起新注册的用户,可享受新人“VIP视频”礼包哦,注册后记得添加微信客服:miaov_xy 来获取哦







分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP