如何添加背景图片
background-image 会在元素的内容、内边距和边框后面绘制一张图片。默认情况下,它从内边距盒子的左上角开始,保持原始尺寸,并重复平铺以填满盒子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Background image</title>
<style>
body { font-family: system-ui, sans-serif; }
.dots {
/* a 24x24 image: one blue dot */
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Ccircle cx='12' cy='12' r='4' fill='%232563eb'/%3E%3C/svg%3E");
height: 120px;
padding: 16px;
border: 2px solid #111827;
font-weight: 600;
}
</style>
</head>
<body>
<div class="dots">One 24px image, repeated to fill the box</div>
</body>
</html>
在真实项目中,url() 指向一个文件:url("images/hero.jpg")。路径相对于包含它的样式表(如果写在 <style> 元素里,则相对于页面)。本页的示例使用以 data: URL 形式内联写入的小型 SVG 图片,所以在任何地方都能运行。
有两点一开始就要知道:
- 背景不会给元素提供尺寸。 一个设置了背景图片的空
div 高度为 0px。要给它内容、内边距、height 或 aspect-ratio。
- 背景图片只是装饰。 屏幕阅读器会跳过它,它也没有替代文本。承载意义的图片应该放在
<img> 元素中。
background-size:cover、contain 和长度值
background-size 用来缩放图片。两个关键字都会保持图片的比例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>cover vs contain</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 14px; }
.row { display: flex; gap: 12px; flex-wrap: wrap; }
.box {
--landscape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='200' viewBox='0 0 400 200'%3E%3Crect width='400' height='200' fill='%23bfdbfe'/%3E%3Ccircle cx='320' cy='50' r='24' fill='%23f59e0b'/%3E%3Cpath d='M0 200L120 70L220 200Z' fill='%2316a34a'/%3E%3Cpath d='M140 200L270 90L400 200Z' fill='%2315803d'/%3E%3C/svg%3E");
width: 160px; height: 160px;
background: var(--landscape) center / auto no-repeat, #e5e7eb;
border: 2px solid #111827;
}
.cover { background-size: cover; }
.contain { background-size: contain; }
.stretch { background-size: 100% 100%; }
</style>
</head>
<body>
<div class="row">
<div><div class="box"></div>auto (400x200, cropped)</div>
<div><div class="box cover"></div>cover</div>
<div><div class="box contain"></div>contain</div>
<div><div class="box stretch"></div>100% 100% (distorted)</div>
</div>
</body>
</html>
这张图片的宽度是高度的两倍,而每个盒子都是正方形。
| 值 | 效果 |
|---|
auto(默认值) | 图片自身的尺寸 |
cover | 缩放到完全填满盒子,多出的部分被裁掉 |
contain | 缩放到整张图片都能放下,两侧留下灰色区域 |
200px | 宽 200px,高度按比例 |
50% auto | 宽度为盒子的一半,高度按比例 |
100% 100% | 正好等于盒子的尺寸;比例不同时图片会变形 |
cover 是首屏横幅和卡片的常用选择。contain 适合那些绝对不能被裁掉的 logo 和插图。
background-position 和 background-repeat
background-position 决定图片在盒子中的位置,可以使用关键字(top、center、bottom、left、right)、百分比或长度值。background-repeat 控制平铺方式。试试不同的值:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Position and repeat</title>
<style>
body { font-family: system-ui, sans-serif; }
#box {
height: 140px; margin-top: 10px;
border: 2px solid #111827;
background-color: #f3f4f6;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Ccircle cx='12' cy='12' r='4' fill='%232563eb'/%3E%3C/svg%3E");
background-size: 48px;
}
label { display: block; margin-top: 6px; }
</style>
</head>
<body>
<label>background-position: <input id="pos" value="center" size="18"></label>
<label>background-repeat: <input id="rep" value="no-repeat" size="18"></label>
<div id="box"></div>
<script>
const box = document.getElementById('box');
const pos = document.getElementById('pos');
const rep = document.getElementById('rep');
const show = () => {
box.style.backgroundPosition = pos.value;
box.style.backgroundRepeat = rep.value;
};
pos.addEventListener('input', show);
rep.addEventListener('input', show);
show();
</script>
</body>
</html>
试试位置值 top right、bottom 10px right 20px 和 25% 75%,以及重复值 repeat-x、repeat-y、space(平铺时留出间隙,不裁切任何一块)和 round(调整每块的大小,让盒子里正好放下整数块)。
多层叠加:多个背景和文字遮罩
background-image 接受一个用逗号分隔的列表。第一层绘制在最上面。常见的用法是在照片上叠一层半透明渐变,让白色文字保持清晰可读:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Overlay</title>
<style>
body { font-family: system-ui, sans-serif; margin: 0; }
.hero {
--landscape: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='200' viewBox='0 0 400 200'%3E%3Crect width='400' height='200' fill='%23bfdbfe'/%3E%3Ccircle cx='320' cy='50' r='24' fill='%23f59e0b'/%3E%3Cpath d='M0 200L120 70L220 200Z' fill='%2316a34a'/%3E%3Cpath d='M140 200L270 90L400 200Z' fill='%2315803d'/%3E%3C/svg%3E");
background-image:
linear-gradient(rgb(17 24 39 / 10%), rgb(17 24 39 / 75%)),
var(--landscape);
background-size: cover;
background-position: center;
aspect-ratio: 16 / 7;
display: flex; align-items: end;
padding: 20px; box-sizing: border-box;
color: white;
}
h1 { margin: 0; font-size: 32px; }
</style>
</head>
<body>
<div class="hero" id="hero"><h1>Readable over an image</h1></div>
</body>
</html>
aspect-ratio 给空盒子提供了高度,background-size: cover 同时作用于两层。更多渐变用法,请看 CSS 渐变。
background 简写
background 在一行中设置所有背景属性。尺寸必须紧跟在位置之后,用斜杠隔开,而颜色要写在最后一层:
.hero {
background: url("hero.jpg") center / cover no-repeat, #1f2937;
}
/* the same as */
.hero {
background-image: url("hero.jpg");
background-position: center;
background-size: cover;
background-repeat: no-repeat;
background-color: #1f2937;
}
图片加载期间以及加载失败时,会显示备用颜色。简写中没有写出的属性都会被重置为默认值,所以要先写简写,再写单独的属性。
其他背景属性
| 属性 | 作用 |
|---|
background-attachment: fixed | 页面滚动时图片固定不动(iOS Safari 会忽略) |
background-origin | 位置从边框、内边距还是内容的边缘开始计算 |
background-clip | 背景绘制到哪里,包括用 text 填充文字 |
background-blend-mode | 把各层混合在一起,比如 multiply |
常见错误
- 路径写错。 样式表中的
url() 是相对于 CSS 文件的,而不是相对于 HTML 页面。
- 空元素。 它没有高度,所以图片无处显示。
- 忘了写
no-repeat,在使用 contain 或小图片时,图片会平铺。
- 用
100% 100% 拉伸图片,而你其实想要的是 cover。
- 把重要图片做成背景。 内容图片请使用带替代文本的
<img>;屏幕阅读器看不到背景。
- 包含空格或引号的
data: URL 没有加引号。 始终写成 url("...")。