子元素绝对定位,造成 body 背景色消失问题?

问题遇到的现象和发生背景

今天练习做登录页,给 body 设置背景色,然后给 login 盒子加上绝对定位后,发现背景色消失。

问题相关代码
<body>
  <div class="login">
    <h2>用户登录</h2>
    <form action="">
      <input type="text" placeholder="请输入用户名" />
      <input type="password" placeholder="请输入密码" />
      <div class="captcha">
        <input type="text" placeholder="请输入验证码" />
        <img src="images/captcha.png" alt="" />
      </div>
      <button class="submit">登录</button>
    </form>
  </div>
</body>
  *{
    margin: 0;
    padding:0;
    box-sizing: border-box;    
  }

  body{
    background:linear-gradient(100deg, #eef6fd, #62b1fb);
  }

  .login {
    width: 400px;
    height: 320px;
    position: absolute;    
    right:15%;
    top:25%;
    background-color: #FFF;
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
    display: flex;
    flex-direction: column;
    align-items: center;
  }
我的解答思路和尝试过的方法

网上查了一下,说是子元素因为定位,脱离的文档流,然后 body 的高度丢失问题造成的,只要把绝对定位取消掉,背景色又回来了。不过这不是解决问题的思路。

目前发现的解决方法:

  • 给 body 上高度: height: 100vh;
  • 加一个不定位的空子元素,如 <div>&npsp;</div>

后来我发现不设置 body 高度,只要把全局设置的 margin: 0 关闭,或者给 body 上个 margin 值也可以让 body 的背景色回来。F12查看发现 body 有了 margin 值,但是依然没有高度。但是背景色却能回来。

虽然问题解决了,但是我不知道是什么原因造成的。望有懂的小伙伴解答一下。

望解惑

要点1: 假设html标签元素a的position定义为absolute的话,此元素会以包含自身的最近的postion定义为absolute或者relative的标签元素b为参照进行定位
要点2: 如果找到b标签元素,但是b标签元素高度未定义时,则b标签元素高度默认为其内部符合文档流排列的元素高度;如果b标签元素内除了标签元素a之外,再无其他元素内容,则b标签高度为0
要点3:如果标签元素a定义的高度大于 b标签元素高度时,在b标签元素未设置 overflow: hidden;情况下,则标签元素a的一部分会在b标签元素外边; 如果b标签元素设置了 overflow: hidden; 这标签元素a的超出b标签元素外的那部分在页面上是隐藏的
要点4:如果b标签元素时body标签,body标签元素中只要存在文本或者符合文档流排列的元素,其高度最小都是整个页面高度(内容超多一屏时出现滚动条);但同时body只存在标签a的话,body的高度也是0

上边标签元素a、b是方便理解, a不是html中的超链接a标签

解决:
1、给body手动设置宽高

body {
  width: 100vw;
  height: 100vh;
}

2、给body标签内添加任意符合文档列排列的元素(此元素display属性不能定义为none, 保证此元素在dom树上; 可以设置visibility: hidden;)即可

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>登录</title>
  <style>
    *{
        margin: 0;
        padding:0;
        box-sizing: border-box;    
    }
    
    body {
        background:linear-gradient(100deg, #eef6fd, #62b1fb);
    }
    
    .login {
        position: absolute;
        top:25%;
        left: 50%;
        transform: translate(-50%);
        width: 400px;
        height: 320px;
        background-color: #FFF;
        box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
        display: flex;
        flex-direction: column;
        align-items: center;
    }
</style>
</head>
  <body>
    <div style="visibility: hidden;">1</div>
    <div class="login">
      <h2>用户登录</h2>
      <form action="">
        <input type="text" placeholder="请输入用户名" />
        <input type="password" placeholder="请输入密码" />
        <div class="captcha">
          <input type="text" placeholder="请输入验证码" />
          <img src="images/captcha.png" alt="" />
        </div>
        <button class="submit">登录</button>
      </form>
    </div>
  </body>
</html>

这篇文章解释的详细
https://blog.csdn.net/weixin_44786530/article/details/124670497