为什么给 body 设置背景会直接铺满整个视口?

当我们在进行网页开发时,通常会遇到需要设置铺满整个页面的背景图的需求,此时我们可以选择创建一个 width: 100vw; height: 100vh<div> 盒子,并设置其背景,这样就可以铺满整个视口。

为 body 设置背景

当然,我们也会选择直接将背景颜色或背景图片设置在 <body> 标签上,此时背景颜色或背景图片便会自动铺满整个视口。

如图:

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>
    body {
      background: linear-gradient(to right, #ff7e5f, #feb47b);
    }
  </style>
</head>
<body>
  
</body>
</html>

但当我们查看结构时会发现:<body> 的高度并没有占据整个视口。

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>
    body {
      background: linear-gradient(to right, #ff7e5f, #feb47b);
    }
  </style>
</head>
<body>
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
  ...
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
</body>
</html>

这与我们平时使用的盒子模型不相符。

body 的背景

回顾知识点:body 元素的默认尺寸行为

  • 宽度 :作为块级元素,body 默认会继承自其父容器 <html>,而 <html> 的宽度默认等于视口宽度(width: 100%)。
  • 高度:未设置高度时,body 的高度由内容撑开(内容高度 < 视口高度时,body 高度 = 内容高度;内容高度 > 视口高度时,body 高度 = 内容高度)。

当我们给 <body> 设置背景时,浏览器会遵循背景的「画布蔓延」机制进行渲染

背景的「画布蔓延」机制

  • <body> 设置背景且 <html> 元素没有设置背景时,浏览器会将 body 的背景「提升」渲染到根元素(<html>)的绘制层上。
  • 这是 CSS 规范中的特殊处理(CSS2.1 规范 Section 14.2)。

具体表现

  • 视觉覆盖视口 :即使 body 的实际高度小于视口高度,body 的背景颜色/图片会看似覆盖整个视口,因为浏览器将其渲染在 <html> 层。
  • 元素尺寸未改变:此时 body 的实际尺寸仍然由内容决定,开发者工具中检查 body 的高度可能小于视口高度。

验证实验

根据上面的知识,我们可以得出一个结论:如果我们同时给 <html><body> 设置背景,那么 <body> 的背景将不会再占满整个视口,而是正常的将背景渲染在 padding-box

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>
    html {
      background-color: #ff7e5f;
    }
    body {
      background-color: #feb47b;
    }
  </style>
</head>
<body>
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
  <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Doloribus, deleniti.</p>
</body>
</html>

总结

为什么给 body 设置背景会直接铺满整个视口?

回答:<body> 的背景属性会被提升到根元素 <html> 的绘制层,从而覆盖整个视口(即"画布蔓延")。我们实际看到的背景其实是 <html> 元素绘制层的背景。

规范建议开发者通过 <body> 而非 <html> 设置页面背景,以确保兼容性和预期渲染效果。

REFERENCED

CSS2.1 规范 Section 14.2

For HTML documents, however, we recommend that authors specify the background for the BODY element rather than the HTML element. For documents whose root element is an HTML "HTML" element or an XHTML "html" element that has computed values of 'transparent' for 'background-color' and 'none' for 'background-image', user agents must instead use the computed value of the background properties from that element's first HTML "BODY" element or XHTML "body" element child when painting backgrounds for the canvas, and must not paint a background for that child element. Such backgrounds must also be anchored at the same point as they would be if they were painted only for the root element.

相关推荐
q***33377 分钟前
SpringMVC新版本踩坑[已解决]
android·前端·后端
亿元程序员33 分钟前
做了十年游戏,我才意识到:程序员最该投资的,是一台专业的编程显示器
前端
IT_陈寒1 小时前
Python高手都在用的5个隐藏技巧,让你的代码效率提升50%
前端·人工智能·后端
lcc1871 小时前
Vue3 ref函数和reactive函数
前端·vue.js
艾小码1 小时前
还在为组件通信头疼?defineExpose让你彻底告别传值烦恼
前端·javascript·vue.js
gnip1 小时前
docker总结
前端
槁***耿1 小时前
TypeScript类型推断
前端·javascript·typescript
带只拖鞋去流浪1 小时前
迎接2026,重新认识Vue CLI (v5.x)
前端·vue.js·webpack
c***V3234 小时前
Vue优化
前端·javascript·vue.js
李@十一₂⁰6 小时前
HTML 特殊字体符号
前端·html