前言

背景

最近在做一个小程序的项目,需要把一个子组件的高度占满整个页面,但是在子组件中设置了 height: 100%; 还是不行。

环境

  • Chrome: 81
  • 小程序:2.11.x

高度占满

查阅了一些资料以后发现,并不是子组件中设置的百分百高度没有生效,而是他的父组件没有设置高度。

以更普遍的 html 为例。

<div class="content">
  Hello, World!
</div>
.content {
  height: 100%;
  background-color: blue;
}

看似已经将顶级元素 div 设置为百分之百的高度了,但实际上 div 还有父级元素 body,body 还有父级元素 html,他们的默认高度都是 0。因此要让 div 占满高度,首先要将 html 和 body 的高度设置成 100%。

html {
  height: 100%;
}

body {
  height: 100%;
}

.content {
  height: 100%;
  background-color: blue;
}

到这里,div的高度就已经占满整个浏览器窗口了。

边距

浏览器默认外边距

但是我们还发现另外一个问题,就是不光占满了窗口,还占多了,竟然出现了滚动条。明明是百分之被,为什么会出现滚动条呢?通过开发者工具可以看出来,浏览器默认为 body 元素设置了外边距 8px,假如窗口高度是 100px,body 高度也是 100px,div 的高度也是 100px,但是由于 body 存在上下两个 8px 的外边距,因此实际高度是 116px,超出窗口高度的 16px 就需要滚动条了。

body {
  display: block;
  margin: 8px;
}

100-percent-height-margin

滚动条的问题也很好解决,只需要覆盖掉默认的外边距就好了。

* {
  margin: 0;
  padding: 0;
}

子组件自定义内边距

这个时候,我们想设置一下子组件的样式,比如给子组件加了一个上内边距。

.content {
  height: 100%;
  background-color: blue;
  padding-top: 30px;
}

我们会惊喜的发现,滚动条又回来了!这到底是怎么回事。这就要说到盒模型和其重要的属性 box-sizing 了。浏览器在计算元素的高度时,会参考元素的 box-sizing 属性,我们来看一下这个属性的定义和可选值表示的意思。

  • content-box 是默认值。如果你设置一个元素的宽为 100px,那么这个元素的内容区会有 100px 宽,并且任何边框和内边距的宽度都会被增加到最后绘制出来的元素宽度中。
  • border-box 告诉浏览器:你想要设置的边框和内边距的值是包含在 width 内的。也就是说,如果你将一个元素的 width 设为 100px,那么这 100px 会包含它的 border 和 padding,内容区的实际宽度是 width 减去 (border + padding) 的值。大多数情况下,这使得我们更容易地设定一个元素的宽高。

那么就很明确了,之所以出现了滚动条,是因为子组件的高度被设置成了 100px + 30px = 130px,解决方案也很直接,将 box-sizing 的值设置成 border-box,即所谓的 IE 盒模型就可以解决问题了。

小程序

最后回到小程序,小程序和标准的浏览器不同,每个页面的顶级元素是 page,因此只需要将 page 的高度设置成 100% 就可以了。

page {
  height: 100%;
}

参考资料