background-image
background-image 相信读者都用过,就是用来设置背景图片的,可能一些读者会习惯于把背景图片直接设置到 background 里面,实际上 background 是一个简写属性,包含了 background-image,在 background-image 里面,一般我们填写的格式是 url(图片路径),但实际上 CSS 3 可以生成自己生成渐变图片,实际上就是函数,一个是 linear-gradient(),另一个是 radial-gradient(),我们在 CSS 中调用这两个函数,就可以给我们生成一张渐变图片,这个渐变图片可以放在 CSS 中任何可以放图片的位置上去。这两个函数可以生成不同类型的渐变图像,即线性渐变和径向渐变,这个放在后面再详细介绍,读者这里只需要记住这俩函数可以生成渐变图像即可。
这里先试一下
css
div {
width: 100px;
height: 100px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border: 1px solid red;
background-image: linear-gradient(red, yellow)
}
这样就生成了一个渐变的背景图像。
特别强调,渐变不是一种颜色,而是 CSS 提供的一个渐变图像生成器,是图像,调用函数生成的是一个渐变色的图像,如果写到
background-color中是不生效的。
在 CSS 3 中,允许我们为 background-image 设置多个值,多个值中间用逗号隔开。
当我们设置多个图片后,要为多个图片设置 background-size, background-position 这类属性的话,就要用逗号隔开。
css
div {
width: 1000px;
height: 1000px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border: 1px solid black;
background-image: url(http://img.zcool.cn/community/018d9158a16b34a8012060c8d9596a.jpg@2o.jpg), url(http://www.hereinuk.com/wp-content/uploads/2017/06/12-22.jpg);
background-size: 300px 600px, 600px, 300px;
background-position: 0 0, 300px 0;
background-repeat: no-repeat;
}
从这里其实可以看出,为了让两个图片并排显示出来,我都要为第二张图片设置一个位置,也就是说如果不为多张图片设置位置,多张图片默认是叠在一起的,并且这个重叠规则和前面多个 box-shadow 那儿一致,都是先写的会在逻辑的最上层。
这个属性的用处其实就是一个备用图片,当我写上两个图片之后,如果第一个图片加载出问题了,比如服务器崩了,源文件被删了,那也有第二张图片可以顶上,或者用第二张图片提示用户图片没加载出来,这样就有一个容错机制,让用户体验会更好。

读者可以看到,这两个图片加载其实是异步的,也就是说是同时进行加载的,加载第一张图片的同时也会加载第二张图片,这个时候其实我第二张图片就可以放个 “加载中” 的图片,由于这个图片很小,会很快加载进来,第一张图片加载进来之后就会立刻覆盖这张 “加载中”的图片。
background-clip
接下来我们来深入了解一下背景这个东西
css
div {
width: 600px;
height: 600px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border: 50px solid transparent;
background-image: url(http://img.zcool.cn/community/018d9158a16b34a8012060c8d9596a.jpg@2o.jpg);
background-size: 200px 400px;
padding: 50px;
}在这个样式中,给盒子设置了 padding 和透明边框,我们看一下背景图片默认的显示范围

从参考线可以看出,背景图片此时作用到了内容区,内边距和边框三个区域,或者边框盒,如果我此时想让背景图片只作用到内容盒,或者填充盒,则只需要设置 background-clip 即可,取值有三个,border-box, padding-box, content-box
如果读者对于
padding-box,content-box和border-box这些概念并不了解,可以参考 7.盒模型

当我们将 background-clip 设置为 content-box,那么背景的作用范围就只有 content-box,不会做用到 padding 和 border 的区域。
实际上 background-clip 还有一个属性值,就是 text,这个 text 的属性是一个实验性的属性,兼容性问题可以参考 background-clip - CSS:层叠样式表 | MDN,截止 2024 年 5 月 6 日,所有主流浏览器均完全支持,所以不需要再加厂商前缀。

background-clip:text; 的作用就是让背景颜色的显示范围为文本区域,设置这个属性的同时将 color 需设置为 transparent,将文字颜色边透明,文字就会呈现背景的样式。
background-origin
再退回去继续看

我们不设置 background-clip,默认是 border-box,也就是背景可以作用到边框盒,此时我们看背景图片的起始位置,我们会发现它并不是从最左上角开始的。

我们选中 padding 可以验证,此时背景图片是从 padding-box 开始的,也就是从填充盒的左上角开始的,去掉 repeat 可能会看的更清楚

去掉 repeat 之后,图片只会显示一张,此时可以很清晰地看到图片是从 padding-box 的左上角开始的,图像的起始位置我们也可以通过 background-origin 进行修改,也是可以填 border-box, padding-box, content-box

当我们把 background-origin 设置为 border-box,图像的起始位置就从 border-box 开始了。
很显然,由于不设置
background-origin的时候,背景图片默认是从填充盒开始的,所以background-origin的默认值为padding-box
实际上
background-origin是指background-position:0 0;的起始位置,也就是背景图片从哪里开始定位,background-position的定位就是基于background-origin的
background-repeat
在 CSS 3 中,background-repeat 也提供了两个新属性,分别是 round 和 space,这两个属性和前面 border-image-repeat 其实是一样的,round 会自适应平铺,比如一行可以放下 3 张图片多一点,此时就只会放下三张图片并且进行拉伸,如果一行可以放下四张图片多一点,就会放下四张图片进行拉伸填满,也就是把那多一点给他通过拉伸去掉,保证每一行和每一列都是整数张图片。space 类似,也保证每一行每一列都能放下整数张图片,不同的是 space 不进行拉伸,保持原尺寸,通过给图片与图片之间添加空白间隙保证了整数张图片。
还可以这样写
background-repeat:round space;,也就是横着是round,纵向是space
background-attachment
接下来再看一下 background-image 这个东西,考虑这样一个场景
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.test {
width: 300px;
height: 600px;
border: 1px solid black;
margin-left: 100px;
margin-top: 100px;
font-size: 20px;
overflow: scroll;
}
</style>
</head>
<body>
<p class="test">
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores eligendi suscipit obcaecati iste
necessitatibus ipsa beatae! Animi reprehenderit praesentium pariatur odit ad laborum dolor assumenda dicta,
consequuntur fugit expedita cumque blanditiis qui aperiam eos cupiditate error voluptatem mollitia reiciendis.
Totam vel, numquam ratione praesentium architecto voluptatem, est minus cupiditate odio voluptates similique
fugiat aliquam cum sapiente repellendus illo. At voluptatibus alias inventore cumque esse sequi ad, dignissimos
iste autem quod. Magni perferendis cupiditate harum soluta exercitationem vitae ab quaerat, ea in officiis sequi
omnis libero aliquid eius autem, est expedita molestiae, deserunt cumque ut neque corporis unde odio mollitia?
At!Lorem ipsum dolor sit amet consectetur, adipisicing elit. Maiores eligendi suscipit obcaecati iste
necessitatibus ipsa beatae! Animi reprehenderit praesentium pariatur odit ad laborum dolor assumenda dicta,
consequuntur fugit expedita cumque blanditiis qui aperiam eos cupiditate error voluptatem mollitia reiciendis.
Totam vel, numquam ratione praesentium architecto voluptatem, est minus cupiditate odio voluptates similique
fugiat aliquam cum sapiente repellendus illo. At voluptatibus alias inventore cumque esse sequi ad, dignissimos
iste autem quod. Magni perferendis cupiditate harum soluta exercitationem vitae ab quaerat, ea in officiis sequi
omnis libero aliquid eius autem, est expedita molestiae, deserunt cumque ut neque corporis unde odio mollitia?
</p>
</body>
</html>
在这个场景下,我们设置一个背景图看一看

可以看到,随着滚动条滚动,背景图片是不滚动的,background-attachment 的默认值为 scroll,即相对于背景窗口进行定位,不会随着滚动条滚动。
background-attachment 还有两个值,分别是 local 和 fixed,如果设置为 local,则这个背景就会跟随滚动条滚动。 ^420 b 34

还有一个值是 fixed,fixed 这个值和 position 中的 fixed 一样,都是基于视口进行定位,注意区分 fixed 和 scroll,一个是基于视口定位,一个是基于窗口定位,视口是浏览器,窗口是这个滚动的元素。

希望这个动图能让读者感受到二者区别,fixed 是基于窗口进行定位的,而 scroll 是基于这个 DOM 元素定位的,读者可以这样理解,基于谁定位,那位置就跟着谁走,scroll 是基于设置背景的这个 DOM 定位的,那就是跟着这个 DOM 走的,当我移动滚动条,让这个 DOM 往上走了,那背景也会跟着往上走,而 fixed 是基于浏览器定位的,就只会跟着浏览器走,哪怕这个 DOM 元素本身往上走了,背景位置也不会变化,只有浏览器位置发生变化了背景位置才会发生变化。
读者可以把
local理解为position中的absolute,把fixed和scroll都理解为position中的fixed,只不过二者的基准不一样,fixed基于浏览器,scroll基于设置背景的 DOM 元素,可以把这个 DOM 元素看成一个小浏览器应该就好理解了。
这个
fixed有时候可以作出一些很炫酷的效果
CSS 3 中为 background-size 添加了两个新取值,cover 和 contain,这个两个取值和 object-fit 其实是一样的,这两个值都不会改变图片原有尺寸,且都会用一张图片填充背景,cover 保证会完全覆盖整个容器,但可能不会包含整张图片,而 contain 则是保证图片能完整地在容器内显示,但可能并不能填满容器,或者说容器里可能会有一些 repeat 出现。