Skip to content

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)
}

0032626548b0095faab0c5449821ce0e_MD5

这样就生成了一个渐变的背景图像。

特别强调,渐变不是一种颜色,而是 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;
        }

21c8aa834ec2ac58f996aa4c2b7794fa_MD5

从这里其实可以看出,为了让两个图片并排显示出来,我都要为第二张图片设置一个位置,也就是说如果不为多张图片设置位置,多张图片默认是叠在一起的,并且这个重叠规则和前面多个 box-shadow 那儿一致,都是先写的会在逻辑的最上层。

这个属性的用处其实就是一个备用图片,当我写上两个图片之后,如果第一个图片加载出问题了,比如服务器崩了,源文件被删了,那也有第二张图片可以顶上,或者用第二张图片提示用户图片没加载出来,这样就有一个容错机制,让用户体验会更好。

59ae2a8412b04d581dc20e4fd3fd539d_MD5

读者可以看到,这两个图片加载其实是异步的,也就是说是同时进行加载的,加载第一张图片的同时也会加载第二张图片,这个时候其实我第二张图片就可以放个 “加载中” 的图片,由于这个图片很小,会很快加载进来,第一张图片加载进来之后就会立刻覆盖这张 “加载中”的图片。

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 和透明边框,我们看一下背景图片默认的显示范围

3282d8de641e3a03d4ed86440880f34b_MD5

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

如果读者对于 padding-box,content-box 和 border-box 这些概念并不了解,可以参考 7.盒模型

3a48849191dec288e985f016e955baca_MD5

当我们将 background-clip 设置为 content-box,那么背景的作用范围就只有 content-box,不会做用到 padding 和 border 的区域。

实际上 background-clip 还有一个属性值,就是 text,这个 text 的属性是一个实验性的属性,兼容性问题可以参考 background-clip - CSS:层叠样式表 | MDN,截止 2024 年 5 月 6 日,所有主流浏览器均完全支持,所以不需要再加厂商前缀。

23df680d63131c2f747d5b80897da793_MD5

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

background-origin ​

再退回去继续看

eff48fca51f88d19e58145eafe4118bd_MD5

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

db4a02d1c6fab07f55ea46e66378c07a_MD5

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

e6eacbe9fd4edfdcbeb0cd5e4a63b1f3_MD5

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

85fc54075037caf23a1e23a7e3816cc3_MD5

当我们把 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>

941a46e4c8584c48833e977392ba6e2c_MD5

在这个场景下,我们设置一个背景图看一看

62ef904dbd11bbc1404426b9af159dc8_MD5

可以看到,随着滚动条滚动,背景图片是不滚动的,background-attachment 的默认值为 scroll,即相对于背景窗口进行定位,不会随着滚动条滚动。

background-attachment 还有两个值,分别是 local 和 fixed,如果设置为 local,则这个背景就会跟随滚动条滚动。 ^420 b 34

58dc81ec05f4e3b5a620fbecd28ff4b8_MD5

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

e1028f090c7d9beec1c2e31d3f8aaff1_MD5

希望这个动图能让读者感受到二者区别,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 出现。

以笔记为镜,可以知得失