条纹背景
原文出处:http://www.w3cplus.com/css3/css-secrets/striped-backgrounds.html
问题
和其他视觉设计相关的媒体一样,在 Web 上各类大小、颜色、角度不同的纹理也非常流行。不过,实现这些纹理的技术却并不理想。通常,我们需要创建独立的位图,如果有需求变更的话都需要重新更改文件。有些开发者使用 SVG 替代位图,但是 SVG 仍然是一种独立的文件,而且其语法也不够友好。那么是否有一种出色的方法让我们直接在 CSS 中创建纹理呢?你会惊喜的发现,我们将在下面的介绍中逐步解决这一问题。
解决方案
首先,假设我们需要一个简单地垂直渐变,颜色从 #fb3
到 #58a
:
图1注:我们初始化的渐变效果
background: linear-gradient(#fb3, #58a);
现在,让我们将两种颜色的过渡点调的更近一些:
图2注:现在渐变占据了整体60%
的高度,其余的部分都是纯色;颜色过渡点的位置在这里使用虚线标识出来
background: linear-gradient(#fb3 20%, #58a 80%);
到此为止,容器顶部20%
的部分是纯粹的 #fb3
,底部20%
的部分是纯粹的 #58a
,所以实际上渐变的部分只占有了容器的60%
。那么如果我们将颜色过渡点(color stops)调整地更近一些(比如 40%
和 60%
,如下图所示),那么渐变的部分就会更小了。这就让我们很自然地联想到,如果颜色过渡点相同会发生什么呢?
图3注:现在渐变占据了整体20%
的高度,其余的部分都是纯色;颜色过渡点的位置在这里使用虚线标识出来
background: linear-gradient(#fb3 50%, #58a 50%);
"如果多个颜色过渡点的位置相同,那么就会在两个颜色之间生成一个无限小的过渡。实际效果就是,一个颜色不再会流畅地过渡到下一个颜色了,而是会突然变成下一个颜色。" — CSS Image Values Level 3
正如下图中看到的那样,已经看不到颜色过渡区域了,只有两种纯色,每种纯色占有容器一半的高度。可以说,我们已经创建了两个宽大的水平纹理。
图4注:现在两个颜色的过渡点位置重合了
因为渐变本质上就是 backgroud-image
,所以我们可以像对待 background-image
一样使用 background-size
调整大小:
background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 30px;
就像下图看到的那样
图5注:我们生成的背景没有使用平铺
我们将两条纹理都缩小到了 15px
的高度。因为背景是可以平铺的,所以我们可以让整个容器填充这种水平纹理了:
图6注:最终的水平渐变
当然,我们还可以创建不等宽的条纹,秘诀就是调节一下颜色过渡点的位置:
background: linear-gradient(#fb3 30%, #58a 30%);
background-size: 100% 30px;
为了避免每次需求变更都需要修改两处颜色过渡点的重复工作,我们可以充分利用规范中介绍的原理:
“如果某个颜色过渡点的位置小于它之前的颜色过渡点,那么该颜色过渡点的位置就会被重置为所有在它前面的颜色过渡点的最大位置。” — CSS Images Level 3
这意味着如果我们将第二个颜色过渡点设置为0
,那么它实际的位置就会被浏览器重置为它前面颜色过渡点的最大位置,而这个位置恰恰就是我们需要的过渡位置。因此,下面的代码不仅仅是和下图 具有同样的效果,而且更加简洁、更具有可维护性:
图7注:不等宽条纹
background: linear-gradient(#fb3 30%, #58a 0);
background-size: 100% 30px;
创建更多颜色的纹理和创建两种颜色的问题同样简单。比如,下面的代码块创建了三种颜色的纹理:
图8注:三色条纹
background: linear-gradient(#fb3 33.3%,
#58a 0, #58a 66.6%, yellowgreen 0);
background-size: 100% 45px;
垂直纹理
水平纹理非常容器创建,但是在 Web 上并不是所有的纹理都是水平的,此外还有很多纹理是垂直的
图9注:垂直条纹,上面:背景没有使用平铺;下面:平铺之后的条纹
而且,在视觉上最受欢迎的纹理可能是倾斜的纹理。值得庆幸的是,CSS 的渐变可以帮助我们实现这样的效果,只是实现的难度各种不同。
实现垂直纹理的代码和水平纹理的非常相似,只有一个主要的差异:一个指定渐变方向的参数。我们可以通过指定这个参数来创建水平纹理,不过对于此次要创建的垂直纹理,使用它的默认值即可(to bottom
)。此外,同样需要创建一个不同的background-size
,原因很明显:
background: linear-gradient(to right, /* or 90deg */
#fb3 50%, #58a 0);
background-size: 30px 100%;
斜纹
在实现了水平纹理和垂直纹理之后,我们可能会尝试通过 background-size
和渐变方向来实现倾斜的纹理(45°
),就像这样的代码:
background: linear-gradient(45deg,
#fb3 50%, #58a 0);
background-size: 30px 30px;
不过,就像下图所示,效果非常不好。
图10注:第一次创建斜纹的失败效果
究其原因,就是因为我们只是将每一条纹理旋转了 45°
,旋转的并不是图形整体。让我们回忆一下使用位图创建斜纹的方法,其中引入的位图和下图相类似。
图11注:这就是创建斜纹的拼接图,看起来是不是很像?
它包含了四条纹理,而不是这里的两条,所以看起来像是无缝连接的。这就是我们需要在 CSS 中重新创建的纹理,所以我们需要更多的颜色过渡点:
background: linear-gradient(45deg,
#fb3 25%, #58a 0, #58a 50%,
#fb3 0, #fb3 75%, #58a 0);
background-size: 30px 30px;
完成后的效果:
图12注:45°
斜纹;虚线用来标识复用的区块
如你所见,虽然我们成功的创建了斜纹,但是看起来比水平和垂直纹理要窄一些。为了回答这个问题,我们需要使用学校里学到的勾股定理来计算直角三角形的各边变长。勾股定理指出,最长边等于其他两边的平方和。在直接三角形中,两条短边相等所以么最长边就等于:
在我们创建的这个斜纹中,background-size
指定的就是三角形最长边的边长,因此纹理的宽度就是直角边的长度。你可以看下图,获得更清晰的解释。
图13注:大小为 20px
的 background-size
将会生成宽度为的条纹
这就是说,如果想要获得原来 15px
的宽度,就需要将 background-size
指定为