《CSS揭秘》第2章-背景与边框

半透明边框

background-clip

难题

假设我们想给一个容器设置一层白色背景和一道半透明白色边框,它的背景会从它的半透明边框透上来

1
2
border:10px solid hsla(0,0%,100%,.5);
background:white;

解决方案

原因 :默认情况下,背景会延伸到边框所在的区域下层。

解决方法 :通过background-clip属性来调整。这个属性的初始值是border-box,更改为padding-box

1
2
3
border: 10px solid hsla(0,0%,100%,.5);
background: white;
background-clip: padding-box;

多重边框

box-shadow

难题

虽然网页开发者可以使用border-image来达到多重边框的效果,但是我们通常希望在 CSS 代码层面以更灵活的方式来调整边框样式。

box-shadow方案

一个正值的扩张半径加上两个为零的偏移量以及为零的模糊值,得到的“投影”其实就像一道实线
边框

1
2
background: yellowgreen; 
box-shadow: 0 0 0 10px #655;

更重要的是,它支持逗号分隔语法,并且是层层叠加的,我们可以创建任意数量的投影

1
2
3
4
background: yellowgreen; 
box-shadow: 0 0 0 10px #655,
0 0 0 15px deeppink,
0 2px 5px 15px rgba(0,0,0,.6);


注意

  1. 投影的行为跟边框不完全一致,因为它不会影响布局,而且也不会受到 box-sizing 属性的影响。
  2. 上述方法所创建出的假“边框”出现在元素的外圈。它们并不会响应鼠标事件,可以通过加上insert来改变

outline方案

优点:灵活,可以使用虚线,可以控制于元素边缘的距离
缺点:只适用两层边框,不贴合边框圆角

灵活的背景定位

background-position,background-origin,calc()

难题

很多时候,我们想针对容器某个角对背景图片做偏移定位并留出一点的空隙,
对于具有固定尺寸的容器来说,使用 CSS 2.1 +复杂的计算可以做到这一点;
当容器元素的尺寸不固定时,这就不可能做到了。

background-position 的扩展语法方案

CSS3中,background-position属性,它允许我们指定背景图片距离任意角的偏移量,只要我们在偏移量前面指定关键字。

1
2
3
background: url(code-pirate.svg) 
no-repeat bottom right #58a; //提供了回退方案,以防浏览器不支持扩展语法
background-position: right 20px bottom 10px;

background-origin 方案


默认情况下,background-position是以padding box为准的,这样边框才不会遮住背景图片。因此,top left 默认指的是padding box的左上角。
background-origin,可以用它来改变这种行为。

1
2
3
padding:10px;
background:url("code-pirate.svg") no-repeat #58a bottom right;
background-origin:content-box;

calc()方案

如果我们仍然以左上角偏移的思路来考虑,其实就是希望它有一个100% - 20px 的水平偏移量,以及100% - 10px 的垂直偏移量。

1
2
background:url("code-pirate.svg") no-repeat;
background-position:calc(100%-20px) calc(100%-10px);

边框内圆角

border-radius,outline,box-shadow

难题


用两个元素可以解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="something-meaningful"><div> 
I have a nice subtle inner rounding,
don't I look pretty?
</div></div>

.something-meaningful {
background: #655;
padding: .8em;
}

.something-meaningful > div {
background: tan;
border-radius: .8em;
padding: 1em;
}

如何用一个元素解决呢?

解决方案

outline并不会跟着元素的圆角走(因而显示出直角),但box-shadow却是会的。因此,如果我们把这两者叠加到一起,box-shadow会刚好填补描边和容器圆角之间的空隙。

1
2
3
4
background:tan;
border-radius: .8em;
box-shadow:0 0 0 .6em #655;
outline:.6em solid #655;

条纹背景

CSS线性渐变,background-size

难题

要想在网页中实现条纹图案。通常,我们的方法是创建一个单独的位图文件,然后每次需要做些调整时,都用图像编辑器来修改它。或者使用SVG来取代位图。

解决方案

“如果多个色标具有相同的位置,它们会产生一个无限小的过渡区域,
过渡的起止色分别是第一个和最后一个指定值。从效果上看,颜色会在那
个位置突然变化,而不是一个平滑的渐变过程。 ”

1
2
background:linear-gradient(#fb3 50%,#58a 50%);
background-siez:100% 30px;

图像如下:

如果要创建超过两种颜色的条纹,也是很容易的。举例来说,下面的代
码可以生成三种颜色的水平条纹。

1
2
background:linear-gradient(#fb3 33.3%,#58a 0,#58a 66.6%,yellowgren 0); //注意颜色排列和百分数
background-siez:100% 45px;

垂直条纹


垂直条纹的代码跟水平条纹几乎是一样的,差别主要在于:
我们需要在开头加上一个额外的参数来指定渐变的方向。

1
2
background:linear-gradient(to right,#fb3 50%,#58a 0);
background-siez:30px 100% ;

斜向条纹


如果我们改变 background-size 的值和渐变的方向,是不是就可以得到斜向(比如
45°)的条纹图案呢?
不行!
原因在于我们只是把每个“贴片”(表示平铺图案中的每个基本单)内部的渐变旋转了 45°,而不是把整个重复的背景都旋转了。
正确做法是:单个贴片包含了四条条纹,而不是两条,只有这样才有可能做到无缝拼接。

1
2
background:linear-gradient(45deg,#fb3 25%,#58a 0,#58a 50%,#fb3 0,#fb3 75%,#58a 0);
background-size:42px 42px;

更好的斜向条纹

在前面的段落中展示的方法还不够灵活,不能变换其他角度。
linear-gradient()radial-gradient()还各有一个循环式的加强版:
repeating-linear-gradient()repeating-radial-gradient()
它们的工作方式跟前两者类似,只有一点不同:
色标是无限循环重复的,直到填满整个背景。

  • 优点
    • 减少了重复:我们要改动任何颜色时只需要修改两处,而不是原来的三处
    • 是在渐变的色标中指定长度,而不是原来的background-size
    • 可以随心所欲地改变渐变的角度


倾斜角为60度的代码如下:

1
background:repeating-linear-gradient(60deg,#fb3,#fb3 15px,#58a 0,#58a 30px);

我们最好用前面的方法来实现水平或垂直的条纹,而用这种方法来实现斜向条纹。
注意 :需要指定高度或宽度。

灵活的同色系条纹

在大多数情况下,我们想要的条纹图案并不是由差异极大的几种颜色组成的,这些颜色往往属于同一色系,只是在明度方面有着轻微的差异。

下面是老方法,在修改时需要修改4个色标

1
background:repeating-linear-gradient(30deg,#79b,#79b 15px,#58a 0,#58a 30px);

下面是新方法,最深的颜色指定为背景色,同时把半透明白色的条纹叠加在背景色之上来
得到浅色条纹

1
2
3
4
5
background:#58a;
background-image:repeating-linear-gradient(60deg,
hsla(0,0,100%,.1),
hsla(0,0,100%,.1) 15px,
transparent 0,transparent 30px);

现在在只需要修改一个地方就可以改变所有颜色了。同时,对于那些不支持CSS 渐变的浏览器来说,这里的背景色还起到了回退的作用。

复杂的背景图案

CSS渐变,“条纹背景”

难题

除了创建各种条纹图案,有时还需要创建网格、波点、棋盘图案

网格

主要思想:多个渐变图案组合起来
我们可以把水平和垂直的条纹叠加起来,从而得到各种样式的网格。

1
2
3
4
5
6
7
//网格条纹不固定
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;

1
2
3
4
5
6
//网格条纹固定
background: #58a;
background-image:
linear-gradient(white 1px, transparent 0),
linear-gradient(90deg, white 1px, transparent 0);
background-size: 30px 30px;

1
2
3
4
5
6
7
8
9
//把两幅不同线宽、不同颜色的网格图案叠加起来
background:#58a;
background-image:
linear-gradient(white 2px,transparent 0),
linear-gradient(90deg,white 2px,tansparent 0),
linear-gradient(hsla(0,0%,100%,.3) 1px,transparent 0),
linear-gradient(hsla(0,0%,100%,.3) 1px,transparent 0);
background-size:75px 75px,75px 75px,
15px 15px,15px 15px;

波点

径向渐变允许我们创建圆形、椭圆,或是它们的一部分,能够创建的最简单的图案是圆点的阵列。

1
2
3
background:#58a;
background-image:radial-gradient(tan 30%,tansparent 0);
backround-size:30px 30px;

我们可以生成两层圆点阵列图案,并把它们的背景定位错开,这样就可以得到真正的波点图案

1
2
3
4
5
6
background:#58a;
background-image:
radial-gradient(tan 30%,tansparent 0),
radial-gradient(tan 30%,tansparent 0);
backround-size:30px 30px;
background-position:0px 0px,15px 15px;

伪随机背景

CSS渐变、条纹背景、复杂的背景图案

难题

自然界中的事物都不是以无限平铺的方式存在的。即使重复,也往往伴随着多样
性和随机性。
重现大自然的随机性是一个挑战,因为 CSS 本身没有提供任何随机功
能。

解决方案

把这组条纹从一个平面拆散为多个图层:
一种颜色作为底色,另三种颜色作为条纹,然后再让条纹以不同的间隔进行重复平铺。

1
2
3
4
5
6
background:hsla(20,40%,90%);
background-image:
linear-gradient(90deg,#fb3 10px,transparent 0),
linear-gradient(90deg,#ab3 20px,transparent 0),
linear-gradient(90deg,#655 20px,transparent 0);
background-size:80px 100%,60px 100%,40px 100%;

我们应该把平铺间距最大的贴片安排在最顶层(在我们的例子中是橙色条
纹)。
这个组合图案中第一个贴片的终点,就是各层背景图像以不同间距重复数次后再次统一对齐的
点。贴片的尺寸实际上就是所有background-size 的最小公倍数。
为了让最小公倍数最大化,这些数字最好是“相对质数”(一种关系,指相互没有公约数)。尽量选择质数,因为质数跟其他任意数字都是相对质数。

连续的图像边框

CSS 渐变,基本的 border-image,“条纹背景”,基本的 CSS 动画

难题

一个元素有一圈装饰性的边框,基本上就是一张图片被裁剪进了边框所在的方环区域。同时,我们还希望这个元素的尺寸在扩大或缩小时,这幅图片都可以自动延伸并覆盖完整的边框区域。
border-image的九宫格伸缩法不适用此难题。
最简单的办法是使用两个 HTML 元素,但不够理想。

解决方案

主要的思路就是在石雕背景图片之上,再叠加一层纯白的实色背景。为了让下层的图片背景透过边框区域显示出来,我们需要给两层背景指定不同的background-clip值。
我们只能在多重背景的最底层设置背景色(上层覆盖下层),因此需要用一道从白色过渡到白色的 CSS 渐变来模拟出纯白实色背景的效果。

1
2
3
4
5
6
7
padding:1em;
border:1em solid transparent;
background:
linear-gradient(white,white),
url(stone-art.jpg);
background-size:cover;
background-clip:padding-box,border-box;


边框的图片有一种怪异的拼接效果。原因是background-origin的默认值是padding-box,因此,图片的显示尺寸不仅取决于padding box的尺寸,而且被放置在了padding box的原点(左上角)。我们看到的实际上就是背景图片以平铺的方式蔓延到border box区域的效果。为了修正这个问题,只需把background-origin也设置为border-box就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
padding:1em;
border:1em solid transparent;
background:
linear-gradient(white,white),
url(stone-art.jpg);
background-size:cover;
background-clip:padding-box,border-box;
background-origin:border-box;

//简写
backdround:
linear-gradient(white,white) padding-box,
url(stone-art.jpg) border-box 0/cover;

这个技巧还可以用在渐变图案上。举个例子,下面这段代码可以生成一种老式信封样式的边框:

1
2
3
4
5
6
7
8
9
padding:1em;
border:1em solid transparent;
background:
linear-gradient(white,white) padding-box,
repaet-linear-gradient(-45deg,
red 0,red 12.5%,
tansparent 0,transparent 25%,
#58a 0,#58a 37.5%,
transparent 0,transparent 50%) 0/5em 5em,

这个技巧的另一个用武之地是生成好玩的蚂蚁行军边框!
我们将会用到“老式信封”技巧的一个变种。我们将把条纹转变为黑白两色,并把边框的宽度减少至 1px,然后再把background-size改为某个合适的值。最后,我们把background-position以动画的方式改变为 100%,就可以让它滚动起来了:

1
2
3
4
5
6
7
8
9
10
11
12
@keyframes ants {to {background-position:100%}};

.marching-ants{
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 inifite;
}

这个技巧不仅在实现蚂蚁行军时很有用,还可以创建出各种特殊样式的虚线框:不管是为虚
线线段指定不同的颜色,还是自定义线段的长度和间隙的长度。

当然,border-image也有它强大的地方,尤其是在搭配渐变图案时更是威力倍增。 举个例子,假设我们需要一个顶部边框被裁切的效果,border-image属性再加上一条由渐
变生成的垂直条纹,并把要裁切的长度在渐变中写好。边框线的粗细交给border-width来控制。

1
2
3
border-top:.2em solid transparent;
border-image:100% 0 0 linear-gradient(90deg,currentColor 4em,transparent 0);
padding-top:1em;

liborn wechat
欢迎您扫一扫上面的微信二维码,订阅我的公众号!