CSS 揭秘 - 第二章,背景与边框

一,半透明边框和背景色的问题

1,background-clip 方案

border-box:背景延伸到边框外沿(但是在边框之下)。

padding-box:边框下面没有背景,即背景延伸到内边距外沿。

content-box:背景裁剪到内容区外沿。

text:css-backgrounds-4 中为 background-clip 加入了值 text,意为仅给文字添加背景。(例子

1
2
3
4
5
6
7
8
9
10
/* Keyword values */
background-clip: border-box;
background-clip: padding-box;
background-clip: content-box;
background-clip: text;

/* Global values */
background-clip: inherit;
background-clip: initial;
background-clip: unset;

二,多重边框的解决方案

1,box-shadow 投影方案(可创建多重实线边框)

利用 box-shadow 支持逗号分隔语法,可以创建任意数量的投影。

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

唯一需要注意的是,box-shadow 是层层叠加的,第一层投影位于最顶层,以此类推。

注意:

1)box-shadow 不会影响布局,不会受到 box-sizing 属性的影响,可以通过 padding 或 margin 来额外模拟出边框所需要占据的空间。

2)出现在元素外圈的 box-shadow 不会响应鼠标事件,可以给 box-shadow 属性加上 inset 关键字,再增加额外的 padding 来解决。

2,outline 描边方案(配合原有的 border,可创建虚实线双重直角边框)

1
2
3
background: yellowgreen;
border: 10px solid #655;
outline: 5px solid deeppink;
优点:

1)可以通过 outline-offset 属性来控制它与元素边缘之间的间距,可以接受负值。

缺点:

1)outline 只适用于双层“边框”的场景,因其并不能接受用逗号分隔的多个值。

2)描边不一定会贴合 border-radius 属性产生的圆角。

3)描边可以不是矩形,需要在不同浏览器中测试最终效果。

三,灵活的背景定位

1,background-position 的扩展语法方案

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

1
2
background: url(code-pirate.svg) no-repeat bottom right #58a;
background-position: right 20px bottom 10px;

2,background-origin 方案(实现偏移量与容器 padding 一致)

每个元素都存在三个矩形框:border-box,padding-box,content-box,默认情况下,background-position 是以 padding-box 为准(这样边框才不会遮住背景图片)。

在 css3-background 中,有一个新属性 background-origin,默认值为 padding-box。
如果把它的值改成 content-box,我们在 background-position 属性中使用的边角关键字将会以内容区的边缘作为基准。

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

3,calc() 方案

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

calc() 函数需要在运算符的两侧各加一个空格,否则会产生解析错误。

四,边框内圆角

1,常规做法(用两个元素实现)

1
2
3
4
5
<div class="something-meaningful">
<div>
I have a nice subtle inner rounding, don't I look pertty?
</div>
</div>
1
2
3
4
5
6
7
8
9
.something-meaningful {
background: #655;
padding: .8em;
}
.something-meaningful > div {
background: tan;
border-radius: .8em;
padding: 1em;
}

2,解决方案(用一个元素实现

1
2
3
<div class="something-meaningful">
I have a nice subtle inner rounding, don't I look pertty?
</div>
1
2
3
4
5
6
7
.something-meaningful {
background: tan;
border-radius: .8em;
padding: 1em;
box-shadow: 0 0 0 .4em #655;
outline: .6em solid #655;
}
思路:

是利用了 outline 不会跟着圆角走,而 box-shadow 会刚好填补 outline 和容器圆角之间的空隙。

注意:

这个方法有一个限制,box-shadow 的扩张半径需要比 outline 的宽度值小,且大于等于圆角半径的一半。

五,条纹背景

解决方案(使用 linear-gradient() 函数 和 background-size 组合实现)

1,水平条纹

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

——CSS 图像(第三版)

1
2
3
4
5
6
/* 等宽条纹 */
background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 30px;
/* 不等宽条纹 */
background: linear-gradient(#fb3 30%, #58a 30%);
background-size: 100% 30px;

如果某个色标的位置值比整个列表中在它之前的色标的位置值都要小,则该色标的位置值会被设置为它前面所有色标位置值的最大值。

——CSS 图像(第三版)

1
2
3
4
5
6
/* 双色条纹 */
background: linear-gradient(#fb3 30%, #58a 0);
background-size: 100% 30px;
/* 三色条纹 */
background: linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0);
background-size: 100% 30px;

2,垂直条纹

1
2
background: to right /*或 90deg */, #fb3 50%, #58a 0;
background-size: 30px 100%;

3,斜向条纹

并不是简单的旋转渐变角度就能得到斜向条纹。

1
2
3
4
5
6
7
8
9
/* 失败的斜向条纹 */
background: linear-gradient(45deg, #fb3 50%, #58a 0);
background-size: 30px 30px;
/* 比预期略细的斜向条纹 */
background: linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0);
background-size: 30px 30px;
/* 勾股定理下预期的斜向条纹 */
background: linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0);
background-size: 42.426406871px 42.426406871px;

4,更好的斜向条纹

linear-gradient() 和 radial-gradient() 各有一个循环式的加强版:

repeating-linear-gradient()repeating-radial-gradient()

1
2
3
4
/* 重复线性渐变:直接在渐变的色标中指定长度 */
background: repeating-linear-gradient(45deg, #fb3, #fb3 15px, #58a 0, #58a 30px);
/* 可指定任意角度的斜向条纹 */
background: repeating-linear-gradient(60deg, #fb3, #fb3 15px, #58a 0, #58a 30px);
建议:

用 linear-gradient() 来实现水平或垂直的条纹,用 repeating-linear-gradient() 来实现斜向条纹。

5,灵活的同色系条纹

1
2
/* 常规的做法 */
background: repeating-linear-gradient(30deg, #79b, #79b 15px, #58a 0, #58a 30px);

更好的做法:不为每种条纹单独指定颜色,而是把最深的颜色指定为背景色,同时把半透明白色的条纹叠加在背景色之上得到浅色条纹。

补充:只有设计上使用了这种做法,才能保证前端做出来的于设计稿一致。

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

六,复杂的背景图案

把多个渐变图案组合起来,可以创建复杂的背景图案。

网格

把用 linear-gradient() 做成的水平和垂直条纹叠加起来,从而得到各种样式的网格。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* 方格纹 */
background: white;
background-image:
linear-gradient(rgba(200, 0, 0, .5) 50%, transparent 0),
linear-gradient(90deg, 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;

波点

使用 radial-gradient() 可以创建圆形、椭圆,或是它们的一部分。

1
2
3
4
5
6
7
8
9
10
11
/* 圆形阵列 */
background: #655;
background-image: radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
/* 波点 */
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;

使用预处理器的mixin来简化代码

1
2
3
4
5
6
7
8
9
10
11
12
@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;
}

body {
@include polka(30px, 30%, #655, tan);
}

棋盘

使用两层 CSS 渐变创建四周有空隙的方块。

1
2
3
4
5
6
/* 白底蓝块 */
background: #58a;
background-image:
linear-gradient(90deg, white 50%, transparent 0),
linear-gradient(white 50%, transparent 0);
background-size: 30px 30px;

使用两个直角三角形组合成方块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* 半张棋盘 */
background: #eee;
background-image:
linear-gradient(45deg, #bbb 25%, transparent 0),
linear-gradient(45deg, transparent 75%, #bbb 0);
background-position: 0 0, 15px 15px;
background-size: 30px 30px;
/* 完整棋盘 */
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-position: 0 0, 15px 15px,15px 15px, 30px 30px;
background-size: 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;

使用预处理器的mixin来简化代码

1
2
3
4
5
6
7
8
9
10
11
12
13
@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: 2*$size 2*$size;
}
body {
@include checkerboard(15px, #58a, tan);
}

SVG实现方案:

1
2
3
4
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill-opacity=".25">
<rect x="50" width="50" height="50" />
<rect y="50" width="50" height="50" />
</svg>

把上面的 SVG 文件以 data URI 的方式内嵌到样式表中(不需要用base64 或 URLencode 来对其编码)

1
2
3
4
5
6
background: #eee url('data:image/svg+xml,\
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill-opacity=".25">\
<rect x="50" width="50" height="50" />\
<rect y="50" width="50" height="50" />\
</svg>');
background-size: 30px 30px;
提示:

出于可读性考虑,如果需要把一句 CSS 代码打断为多行,只需要用反斜杠(\)来转义每行末尾的换行就可以了。

参考:

1,作者的CSS图案库CSS图案库的SVG版

2,Bennett Feely 的图案库

七,伪随机背景

八,连续的图像边框