现代 CSS

CSS秘密花园:随机背景

特别声明:如果您喜欢小站的内容,可以点击申请会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!或添加QQ:874472854(^_^)

CSS Secrets》是@Lea Verou最新著作,这本书讲解了有关于CSS中一些小秘密。是一本CSSer值得一读的一本书,经过一段时间的阅读,我、@南北@彦子一起将在W3cplus发布一系列相关的读后感,与大家一起分享。

CSS Secrets

问题

虽然平铺几何图形很棒,但看起来还是有点乏味。而在自然界中,万事万物皆有不同。即使是在相似中,也充满了变化和随机因素。你可以看一看花圃:虽然花朵具有一致的艳丽,但也各有各的亮点。这个世界上没有任何两朵花是相同的。这就是为什么我们要尝试让背景图案接近真实,而且我们也在尝试让平铺的元素之间尽量减少缝隙,让它们显得浑然天成自成一体,但是这也会让样式文件的大小超出我们的预期。

当你发现了某些独特的特性——比如木头纹理上特定距离就会出现的结,就会打破随机性这种感觉 — Alex Walker, The Cicada Principle and Why It Matters to Web Designers

模拟随机是一件非常具有挑战性的事情,因为 CSS 并没有任何创造随机性的能力。让我们重新拿起条纹这个示例,假设我们想要得到拥有各种颜色和宽度的垂直条纹(让我们简化为四种颜色吧),并且还要让它们之间过渡自然。我们的第一个想法可能就是创建一个渐变:

background: linear-gradient(90deg,
              #fb3 15%, #655 0, #655 40%,
              #ab4 0, #ab4 65%, hsl(20, 40%, 90%) 0);
background-size: 80px 100%;

就像下图看到的那样

随机背景图

图注:实现伪随机条纹的初次尝试,其中所有的颜色都是由相同的线性渐变生成的

非常明显就分辨出了重复元素,这主要是因为它只重复了 80pxbackground-size)。我们可以做得更好吗?

解决方案

对于这一问题,我的第一个想法就是将整个的条纹分成不同块,然后增加这些块的随机性:一个基色和三个条纹层,在不同的距离上实现平铺。通过硬编码颜色过渡点的位置,我们可以改变条纹的宽度,通过使用 backgroud-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%;

因为最顶层的平铺将会最容易被注意到(因为它覆盖了所有的图层),所以我们对最上面的一层施加最大的间歇性间距(在本例中,就是桔黄色条纹)。

随机背景图

图注:第二次尝试,通过不同的 background-size 让不同的图层发生重叠;虚线框内的图案是用来平铺的图案

正如上图中所看到的那样,整体看起来随机多了,但如果我们仔细观察,还是能意识到每 240px 就会有一次重复。也就是说,在此类组合中,所有重复块的偏移量就是第一个非重复条纹终点位置的一倍或数倍。也许你还记得在学校里我们学过的最小公倍数(LCM,Least Common Multiple),它是一个整数集合中所有整数的一倍或多倍。因此,这里条纹块的大小就是背景大小的最小公倍数,即 40/60/80,它们的最小公倍数就是 240

上面的示例就遵循了这一不易察觉的随机性,所以我们需要增大平铺条纹块的大小。感谢数学的存在,无需漫长和痛苦的计算我们就可以实现它,因为我们已经知道了答案。为了达到最大的最小公倍数,那么这些数之间必须互质。在本例中,最小公倍数就是由它们得出来的。比如,3/4/5 就互为质数,所以它们的最小公倍数就是 3 × 4 × 5 = 60。让数值互为质数的最简单方式就是让它们是质数,在数学上质数和其他任何数都互为质数。质数的列表在网络上随处可见。

为了保持最大的随机性,我们甚至使用质数来设计条纹的宽度。这就是我们的代码:

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%;

是的,代码很难看,但是效果如下图所示:

随机背景图

图注:最终的条纹,使用质数来增加随机性

现在我们的条纹至少 41 × 61 × 83 = 207583px 才会平铺一次,完全超出了一个屏幕分辨率所能容纳的数量。

上面的技巧(使用质数增加背景平铺时的随机性)被称为 “The Cicada Principle”,由 Alex Walker 第一次提出。值得注意的是,这不仅仅对背景有用,而且对需要平铺的任何事情都有用。其他的应用包括但不限于:

  • 为一个图库中图片的旋转角度增加一点点随机性,可以使用 :nth-child(an) 选择器,其中 a 为质数。
  • 为动画的运动过程添加一些随机性,那么可以添加多个以质数为时间长度的持续时间(点击这里查看示例

向提出这一技巧的 Alex Walker 致敬, The Cicada Principle and Why It Matters to Web DesignersEric Meyer 随后提出了 Cicadients 这一概念, 其中就包含了将该技巧通过 CSS 渐变添加到背景图片上。Dudley Storey 也就该概念发表了大量非常有价值的文章.

总结

前面介绍的内容,不管是使用渐变实现的线性渐变还是径向渐变,或者说是复杂的纹理背景,都是具有一定的规律性。在这一节中主要向大家阐述了如何实现随机性的背景图效果。

如需转载,烦请注明出处:http://www.w3cplus.com/css3/css-secrets/random-backgrounds.htmlThe 13th Version UA Yeezy Boost 350 Turtle Dove, the perfect version

返回顶部