想必写过 CSS 的同学都用过 box-shadow,它能够给元素设置暗影,添加立体作用。
比方说这样:
但它能做的可不只是暗影,还能够用来做出许多风趣的作用:
比方画蒙娜丽莎:
画星空:
这些作用都是 box-shadow 完成的!
是不是不敢相信?
今日咱们就一起研讨下 box-shadow 的高阶用法,来完成这些作用吧。
先过一下根底:
box-shadow 根底
box-shadow 能够设置 5 个值:x偏移量 y偏移量 暗影含糊半径 暗影分散半径 暗影颜色
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
比方这个案例:
暗影中心点 x 轴偏移了 300px,y 轴偏移了 300px:
那暗影分散半径是啥意思?
看这张图就明白了:
还有暗影含糊半径:
再来看下这几个值:
box-shadow: 300px 300px 30px 100pxblue;
x 轴位移、y 轴位移都是指中心点的位移。暗影的半径便是元素的 width/2 + 分散半径 + 含糊半径。
而且 box-shadow 能够设置多个,经过逗号分隔,也便是多重暗影。
这样就能够用来做一些有意思的工作了:
比方把 width、height 设置为 0,然后设置多个暗影:
width、height 为 0,含糊半径为 0,分散半径为 5px,那整个暗影便是一个 10px * 10px 的方块。
这样设置不同方位的 8 个暗影块便是上面的作用。
假如这样的块多了,是不是就类似像素块那样能展示图画了呢?
没错,蒙娜丽莎便是这么画出来的:
box-shadow 画蒙娜丽莎
全体思路上面已经分析出来了,便是经过 box-shadow 多重暗影设置每个像素块的颜色和方位:
这儿 width、height 为 0,含糊半径为 0,分散半径为 2px,那总体宽高便是 4px。
而每个块的中心点相距 5px,所以会留下一个距离。
咱们试一下:
的确,经过这样一个个暗影块就能把蒙娜丽莎画出来。
然后咱们把距离去掉,也便是把分散半径设置大一点:
现在就连在一起了:
但这样看起来像素感太强了,咱们给它加点含糊半径,比方设置个 4px:
这样好多了:
至此,神秘的蒙娜丽莎的微笑就完成了,只用到了 box-shadow 和一个 div!
这儿是画了蒙娜丽莎,其实各种图片都能画,只要拿到像素数据就行,这个能够经过 canvas 的 getImageData 来拿到。
这儿是一个个摆放的暗影块,那假如随机打算这些暗影块,是不是能够做一些粒子作用呢?
比方星空。
咱们来试一下:
box-shadow 画星空
星空大概是这样的:
画完蒙娜丽莎,咱们知道了能够经过 box-shadow 多重暗影画出任意多个方块。不过那时是顺序摆放的,现在咱们期望把方位打乱,添加一些随机作用。
怎样随机呢?
css 里的确设置不了随机的东西,可是能够经过预处理器来做到,比方 sass。
咱们经过 sass 来一个写循环生成随机 box-shadow 的函数:
@function multiple-box-shadow($n) {
$value: '#{random(2000)}px #{random(2000)}px #FFF';
@for $i from 2 through $n {
$value: '#{$value} , #{random(2000)}px #{random(2000)}px #FFF';
}
@return unquote($value);
}
这段代码是经过 @function 声明 sass 的函数,作用是传入 n,生成随机方位的白色 n 个暗影块。
声明晰一个 $value 的变量作为初始值,然后循环生成 box-shadow 的值加到 $value 里,最终回来 $value,但要用 unquote 把引号去掉。
循环使用 @for $i from xx through yy 的语法,每次循环调用 random 函数生成 2000 内的随机整数。
这样就完成了 n 个随机方位的 box-shadow 的生成逻辑。
然后咱们用一下它:
在 html 里放个 div:
<div id='stars'></div>
给它设置宽高和 box-shadow:
#stars {
width: 1px;
height: 1px;
box-shadow: multiple-box-shadow(700);
}
这儿就没有设置分散半径和含糊半径了,所以暗影块巨细便是元素的宽高。
作用是这样的:
看下现在的 css:
的确有随机生成的 700 个 box-shadow 值。
这便是预处理器的作用。
当然,这种逻辑也能够用 JS 来写,运行时生成随机 box-shadow,可是渲染速度上会比 sass 编译期间生成的方案慢许多。
然后咱们让它动起来,加上 animation:
#stars {
animation: animStar 50s linear infinite;
}
@keyframes animStar{
from{
transform: translateY(0px)
}
to {
transform: translateY(-2000px)
}
}
前面随机生成的 700 个星星的方位便是 0 到 2000px 的,所以这儿是从 0 运动到 -2000px。
先把时间改短点,改成 3s 看下作用:
你会发现有段时间下面全是黑的,没有星星,这是为什么呢?
这个很简单想明白:当 translateY 快到 -2000px 的时分,剩余的部分星星不到一屏,其他的方位自然就没有星星了。
怎样解决这个问题呢?
其实这种仍是比较经典的 CSS 问题,比方轮播图的无缝滚动也是同种原因。
解决方法便是在后面再接一个一模一样的,然后位移到了 -2000px 的时分,马上定位到 0 重新开始。这样就无缝了。
咱们经过伪元素来设置这个:
$shadows-small: multiple-box-shadow(700);
#stars {
width: 1px;
height: 1px;
box-shadow: $shadows-small;
animation: animStar 3s linear infinite;
&:after {
content: " ";
position: absolute;
top: 2000px;
width: 1px;
height: 1px;
box-shadow: $shadows-small;
}
}
注意,这儿要确保两次的 box-shadow 是一样的,所以经过一个变量来保存生成的值,两处都引证这个变量。
这样就无缝了:
但现在仍是有点假,咱们多加两种不同巨细不同运动速度的星星:
当然,个数也不一样,越大的越少,分别生成 200 和 100个,动画时长分别设置 100s 和 150s:
<div id='stars2'></div>
<div id='stars3'></div>
$shadows-medium: multiple-box-shadow(200);
$shadows-big: multiple-box-shadow(100);
#stars2 {
width: 2px;
height: 2px;
box-shadow: $shadows-medium;
animation: animStar 100s linear infinite;
&:after {
content: " ";
position: absolute;
top: 2000px;
width: 2px;
height: 2px;
box-shadow: $shadows-medium;
}
}
#stars3 {
width: 3px;
height: 3px;
box-shadow: $shadows-big;
animation: animStar 150s linear infinite;
&:after {
content: " ";
position: absolute;
top: 2000px;
width: 3px;
height: 3px;
box-shadow: $shadows-big;
}
}
看下作用:
星空的感觉是不是就出来了!
不过现在的代码还有点不高雅,star 的样式重复写了 3 次,已然用了 sass,那能够把它抽成一个 mixin 来复用:
@mixin stars($size, $duration, $boxShadow) {
width: $size;
height: $size;
background: transparent;
box-shadow: $boxShadow;
animation: animStar $duration linear infinite;
&:after {
content: " ";
position: absolute;
top: 2000px;
width: $size;
height: $size;
background: transparent;
box-shadow: $shadows-small;
}
}
三处样式只要 include 这个 mixin,传入参数即可:
#stars {
@include stars(1px, 50s, $shadows-small);
}
#stars2 {
@include stars(2px, 100s, $shadows-medium);
}
#stars3 {
@include stars(3px, 150s, $shadows-big);
}
代码高雅了许多!
悉数 scss 代码如下:
@function multiple-box-shadow($n) {
$value: '#{random(2000)}px #{random(2000)}px #FFF';
@for $i from 2 through $n {
$value: '#{$value} , #{random(2000)}px #{random(2000)}px #FFF';
}
@return unquote($value);
}
$shadows-small: multiple-box-shadow(700);
$shadows-medium: multiple-box-shadow(200);
$shadows-big: multiple-box-shadow(100);
html {
height: 100%;
background: #000;
overflow: hidden;
}
@mixin stars($size, $duration, $boxShadow) {
width: $size;
height: $size;
background: transparent;
box-shadow: $boxShadow;
animation: animStar $duration linear infinite;
&:after {
content: " ";
position: absolute;
top: 2000px;
width: $size;
height: $size;
background: transparent;
box-shadow: $shadows-small;
}
}
#stars {
@include stars(1px, 50s, $shadows-small);
}
#stars2 {
@include stars(2px, 100s, $shadows-medium);
}
#stars3 {
@include stars(3px, 150s, $shadows-big);
}
@keyframes animStar{
from{
transform: translateY(0px)
}
to {
transform: translateY(-2000px)
}
}
总结
box-shadow 咱们一般用来做暗影,但其实也能够用来做一些风趣的作用。
暗影块的巨细是由元素宽高、分散半径、含糊半径这些决议的。
经过多重暗影顺序摆放暗影块能够到达像素块的作用,画出蒙娜丽莎或许其他任意的图片。
也能够经过 sass 预处理器随机生成不同方位的暗影块来做出粒子作用,比方星空。
除了能够随机生成样式外,还能够经过 sass 的 mixin 来抽离相似的代码,多处复用,让 css 代码更高雅。这便是预处理器的含义。
box-shadow 的高阶玩法,你学会了么?