深刻理解CSS系列(二):为何height:100%不生效?

对于height属性,若是父元素heightauto,只要子元素在文档流中(即position不等于fixed或者absolute),其百分比值彻底就被忽略了。这是什么意思呢?首先来看个例子,好比,某小白想要在页面插入一个<div>,但愿满屏显示黑色背景,就写了以下 代码:html

<!DOCTYPE html>
<html lang="en">
<head>
  <title>黑色主题</title>
  <style>
    .box {
      width: 100%; // 这是多余的
      height: 100%; // 这是无效的
      background: #000;
    }
  </style>
</head>
<body>
  <div class="box"></div>
</body>
</html>

而后他发现这个<div>高度永远是 0,哪怕其父级<body>塞满了内容也是如此。事实上,他须要加上这样的设置才行:浏览器

html, body {
 height: 100%;
}

而且仅仅设置<body>也是不行的,由于此时的<body>也没有具体的高度值:布局

body {
 /* 子元素 height:100%依旧无效 */
}

只要通过必定的实践,咱们都会发现对于普通文档流中的元素,百分比高度值要想起做用,其父级必须有一个能够生效的高度值!可是,怕是不多有人思考过这样一个问题:为什么父级没有具体高度值的时候,height:100%会无效?code

网上有种观点认为,若是父元素height: auto,又要让子元素height:100%生效的话,会使得布局进入一种死循环。好比下面的代码:htm

<style>
  .child1 {
    height: 100px;
  }
  .child2 {
    height: 100%;
  }
</style>
<div class="parent">
  <div class="child1"></div>
  <div class="child2"></div>
</div>

他们的推理大概以下:
parent 元素的高度默认为auto。首先,child1的高度为100px, 这时候 parent 的高度也会等于100px, 而后由于 child2 的height: 100%,因此它的高度会等于 parent 的高度也变成了100px,这时候 child1 + child2 的高度是200px ,致使 parent 的高度也变成了200px, 接着 child2 由于height: 100%,高度也要等于 parent 的高度,因此变成了200px,而后就会陷入无限死循环了。资源

这个推论看上去好像有理有据 ,可是,其实是个谬论来着。为何这样说呢?要明白其中的缘由要先了解浏览器渲染的基本原理。首先,先下载文档内容,加载头部的样式资源(若是有的话),而后按照从上而下、自外而内的顺序渲染 DOM 内容。套用本例就是,先渲染父元素 parent,后渲染子元素 child1 , 最后渲染子元素 child2 ,是有前后顺序的。所以,当渲染到child2的时候,父元素高度已经固定为 100px 了。高度不够怎么办?溢出就行了,overflow 属性就是为此而生的。文档

记住,浏览器渲染规则是:静态渲染,一次到位。it

真实的缘由是:若是包含块(即父元素)的高度没有显式指定(即高度由内容决定),而且该元素不是绝对定位,则计算值为auto(这是计算值,是指渲染以后解释的值,并非咱们设置height: auto所指的值)。一句话总结就是:由于解释成了 auto。要知道,auto 和百分比计算,确定是算不了的:io

'auto' * 100/100 = NaN

此时,他们的计算结果是NaN,这就是父元素没有设置高度时,子元素高度百分比不生效的缘由了。class

那有什么办法让高度百分数生效呢?有两种办法。
(1)设定显式的高度值。例如,设置height:600px,或者能够生效的百分比值高度。例如,咱们比较常见的:

html, body {
 height: 100%;
}

(2)使用绝对定位
为何使用绝对定位就能够了呢?由于会使元素具备“格式化高度”。那什么又是格式化高度?

格式化宽度/高度仅出如今“绝对定位模型”中,也就是出如今position属性值为 absolutefixed的元素中。当left/toptop/bottom对立方位的属性值同时存在的时候,元素的宽度/高度表现为“格式化宽度/高度”,其宽度/高度相对于最近的具备定位特性(position属性值不是static)的祖先元素计算。

回到开头提到的盒子,小白设置height不生效的问题,若是用绝对定位方法实现,能够设置他的父元素body为绝对定位,代码以下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>黑色主题</title>
  <style>
    body {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
    }

    .box {
      width: 100%;
      height: 100%;
      background: #000;
    }
  </style>
</head>
<body>
  <div class="box">
  </div>
</body>
</html>
相关文章
相关标签/搜索