6.复杂的背景图案
背景知识:css渐变, “条纹背景”
6.1 网格
把多个渐变图案组合起来,让它们透过彼此的透明区域显现时,就会得到意想不到的图案。
background: white;
background-image: linear-gradient(90deg, rgba(200,0,0,.5), 50%, transparent 0),
linear-gradient(rgba(200,0,0,.5) 50%, transparent 0);
background-size: 30px 30px;
有些时候我们希望网格中每个格子的大小可以调整,而网格线条的粗细同时保持固定。下面展示了使用长度而不是百分比作为色标的场景
background: #58a;
background-image: linear-gradient(white 1px, transparent 0),
linear-gradient(90deg, white 1px, transparent 0);
background-size: 30px 30px;
还可以把两幅不同线宽、不同颜色的网格图案叠加起来
background: #58a;
background-image: linear-gradient(white 2px, transparent 0),
linear-gradient(90deg, white 2px, transparent 0),
linear-gradient(hsla(0,0%,100%,.3) 1px, transparent 0),
linear-gradient(90deg,hsla(0,0%,100%,.3) 1px, transparent 0);
background-size: 75px 75px, 75px 75px,15px 15px, 15px 15px;
6.2 波点
波点是利用径向渐变知识。下面是一个简单的径向渐变
background: #655;
background-image: radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
这里的径向渐变由每个小方块的中心向四周渐变,也就是background-size指定的大小。
下面是一种更加使用的图案:
background: #655;
background-image: radial-gradient(tan 30%, transparent 0),
radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px;
使用background-position属性将两个背景位置错开,第一个值表示水平位置,第二个表示垂直位置,用逗号分隔设置多重。
因为为了达到效果,第二层背景的偏移定位值必须是平铺图案中的每个基本单元宽高的一半,每次修改要修改多处尺寸,可以使用scss
@mixin polka($size, $dot, $base, $accent) {
background: $base;
background-image: radial-gradient($accent $dot, transparent 0),
radial-gradient($accent $dot, transparent 0);
background-size: $size $size;
background-position: 0 0, $size/2 $size/2;
}
@include polka(30px, 30%, #655, tan)
6.3 棋盘
一步一步制作棋盘,首先回想一下制作三角形图案。要制作类似下面这张图案
background: #eee;
background-image: linear-gradient(45deg, #bbb 50%, transparent 0);
background-size: 30px 30px;
每个三角形占据每个单元的一般,修改色标位置为25%。 https://xxxgitone.github.io/2017/03/24/bg-border/06-7.png 我们把色标的顺序反转,便可以创建相反方向的三角形了background: #eee;
background-image: linear-gradient(45deg, transparent 75%, #bbb 0);
background-size: 30px 30px;
组合起来的图形
background: #eee;
background-image: linear-gradient(45deg, transparent 75%, #bbb 0),
linear-gradient(45deg, #bbb 25%, transparent 0);
background-size: 30px 30px;
现在只需要把第二层渐变在水平和垂直方向均移动每个单元的一半,就可以拼接起来。
background: #eee;
background-image: linear-gradient(45deg, #bbb 25%, transparent 0),
linear-gradient(45deg, transparent 75%, #bbb 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px;
产生出了一个正方形,本质上是棋盘的一半,复制一份再创建出另一组正方形。
background: #eee;
background-image: linear-gradient(45deg, #bbb 25%, transparent 0),
linear-gradient(45deg, transparent 75%, #bbb 0),
linear-gradient(45deg, #bbb 25%, transparent 0),
linear-gradient(45deg, transparent 75%, #bbb 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px,15px 15px, 30px 30px;
代码进行优化,可以把这些处在单元顶角的三角形两两组合起来(即把第一组和第二组并为一层渐变,第三组和第四组为一层渐变)
background: #eee;
background-image: linear-gradient(45deg, rgba(0,0,0,.25) 25%, transparent 0,
transparent 75%, rgba(0,0,0,.25) 0),
linear-gradient(45deg, rgba(0,0,0,.25) 25%, transparent 0,
transparent 75%, rgba(0,0,0,.25) 0);
background-position: 0 0, 15px 15px;
background-size: 30px 30px;
使用scss@mixin checkerboard($size, $base, $accent: rgba(0,0,0,.25)) {
background: $base;
background-image: linear-gradient(45deg, $accent 25%, transparent 0,
transparent 75%, $accent 0),
linear-gradient(45deg, $accent 25%, transparent 0,
transparent 75%, $accent 0);
background-position: 0 0, $size $size;
background-size: $size*2 $size*2;
}
@include checkerboard(15px, #58a, tan);
7. 伪随机背景
重复平铺的几何图案很美观,但是看起来和你呆板。用css实现图案的随机平铺。
background: linear-gradient(90deg, #fb3 15%, #655 0, #655 40%,
#ab4 0, #ab4 65%, hsl(20, 40%, 90%) 0);
background-size: 80px 100%;
上面通过background-size来控制图案每隔80px重复一次。规律比较明显,并不是真实的随机平铺。
接下来,把这组条纹从一个平面拆散为多个层面:一种颜色作为底色,另外三种颜色作为条纹,然后再让条纹以不同的间隔进行重复平铺。在色标中定好边框的宽度,用background-size来控制条纹的间距
background: hsl(20, 40%, 90%);
background-image:
linear-gradient(90deg, #fb3 10px, transparent 0),
linear-gradient(90deg, #ab4 20px, transparent 0),
linear-gradient(90deg, #655 20px, transparent 0);
background-size: 80px 100%, 60px 100%, 40px 100%;
但是这里还有一个问题,每隔240px还是会重复一次,红色箭头处。这里每次重复单元正好是background-size的最小公倍数,而40、60、80的最小公倍数就是240。
根据这个逻辑,可以把每个重复单元的尺寸最大化,也就是最小公倍数最大化。为了让最小公倍数最大化,这些数字最好是相对质数(比如,10和27不是质数,但他们是相对质数,最小公倍数为10乘以27)。要达成相对质数,尽量选择质数,于是下面代码
background: hsl(20, 40%, 90%);
background-image:
linear-gradient(90deg, #fb3 11px, transparent 0),
linear-gradient(90deg, #ab4 23px, transparent 0),
linear-gradient(90deg, #655 41px, transparent 0);
background-size: 41px 100%, 61px 100%, 83px 100%;
再想让它重复,早就超出屏幕的分辨率了。
这个技巧被Alex Walker定名为“蝉原则”,通过质数来增加随机真实性。还可以用于其他涉及有规律重复的情况
在图片库中,为每幅图片用细微的伪随机旋转效果时,可以使用:neth-child(a)选择符,且让a是质数。
如果要生成一个动画,而且让它看起来不是按照明显的规律在循环时,可以应用多个时长为质数的动画。
8. 连续的图像边框
背景知识:css渐变、border-image、条纹背景、基本的css动画
border-image
:指定作为元素周围边框的图像。基本原理就是九宫格伸缩法,把图片切割成九块,然后把它们应用到边框相应的边和角。结合实例继续说明
有时候我们想把一幅图案或图片应用为边框,而不是背景。一个元素有一圈装饰性的边框,基本上就是一张图片被裁剪进了边框所在的方环区域,不仅如此,还希望这个元素的尺寸在扩大或缩小的时候,这幅图片都可以自动延伸并覆盖完整的边框区域。
最简单的办法就是使用连个HTML元素,一个元素用来把图片设为背景,另一个元素存放内容
<div class="something">
<div>I have a nice stone art border,
don't I look pertty?
</div>
</div>
.something {
background: url('http://csssecrets.io/images/stone-art.jpg');
background-size: cover;
padding: 1em;
}
.something > div {
background: white;
padding: 1em;
}
如何改进,使用一个元素?
思路:在背景图片之上,再叠加一层纯白的实色背景,为了让下层的图片背景透过边框区域显现出来,需要给两层背景指定不同的background-clip值,最后一个要点在于,我们只能在多重背景的最底层设置背景色,因此需要一道从白色过渡到白色的css渐变来模拟纯白实色背景的效果
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white),
url('http://csssecrets.io/images/stone-art.jpg');
background-size: cover;
background-clip: padding-box, border-box;
发现效果很接近,但是边框的图片有一种怪异的拼接效果。原因是background-origin的默认值是paddin-box,因此,图片的显示尺寸不仅取决于padding box的尺寸,而且被放置在了padding box的原点(左上角)。我们看到的实际上就是背景图片以平铺的方式蔓延到border box区域的效果。修改即可
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white),
url('http://csssecrets.io/images/stone-art.jpg');
background-size: cover;
background-clip: padding-box, border-box;
background-origin:border-box;
简写属性
background:
linear-gradient(white, white) padding-box,
url('http://csssecrets.io/images/stone-art.jpg') border-box 0 / cover;
这个技巧还可以运用到渐图案上,比如制作一个老式信封
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white,white) padding-box,
repeating-linear-gradient(-45deg, red 0, red 12.5%, transparent 0,
transparent 25%, #58a 0, #58a 37.5%, transparent 0, transparent 50%) 0 / 5em 5em;
上面例子可以很容易的通过background-size属性来改变条纹的宽度,通过border属性来改变整个边框的厚度。还可以用border-image来实现。
padding: 1em;
border: 16px solid transparent;
border-image: 16 repeating-linear-gradient(-45deg, red 0, red 1em, transparent 0,
transparent 2em, #58a 0, #58a 3em, transparent 0, transparent 4em);
border-image
也是一个复合属性,包含下面属性
border-image-source
:用在边框的图片的路径
border-image-slice
:图片边框向内偏移
border-image-width
:图片边框的宽度
border-image-outset
:边框图像区域超出边框的量
border-image-repeat
:图像边框是否应平铺(repeated)、铺满(rounded)或拉伸(stretched)
上面例子使用border-image实现,存在一些问题
- 每当我们改变border-image-slice时,都要同时修改border-width来让它们匹配
- 由于不能在border-image-slice属性中使用em单位,只能把边框厚度指定为像素单位
- 条纹的宽度需要在色标的位置信息中写好。
制作蚂蚁行军边框
将边框的宽度减少至1px,修改条纹颜色,便可以出现虚线边框,然后background-size改为某个合适的值。添加动画
@keyframes ants { to {background-position: 100%} }
padding: 1em;
border: 1px solid transparent;
background:
linear-gradient(white, white) padding-box,
repeating-linear-gradient(-45deg, black 0, black 25%, white 0, white 50%) 0 /.6em .6em;
animation: ants 12s linear infinite;
border-image也有它强大之处,尤其是在搭配渐变图案时。比如我们需要一个顶部边框被裁切的效果,就像一般的脚注一样。我们所需要的就是在border-image属性再加上一条由渐变生成的垂直条纹,并把要裁剪的长度在渐变中写好,边框的粗细由border-width来控制。
border-top: .15em solid transparent;
border-image: 100% 0 0 linear-gradient(90deg, currentColor 4em, transparent 0);
padding-top: .5em;
使用了currentColor属性,会根据color属性的变化而自动适应(假设我们希望这条边框跟文字保持相同颜色)
correntColor:这是css3中一个颜色的关键字,这个关键字并没有绑定到一个固定的颜色,而是一直被解析为color。
假如我们想要所有水平割线自动与文本颜色保持一致。可以这么写
hr {
height: .5em;
background: currentColor;
}
很多已有的属性也具有类似的行为。如果你没有给边框指定颜色,它会自动从文本颜色那里得到颜色。