likes
comments
collection
share

父容器设置min-height,子元素height百分比失效 / height: 100%失效尝试解决height: a

作者站长头像
站长
· 阅读数 32

背景

自从之前改博客园主题发现设置了高度但是实际上不是那个高度后(min-height导致的),就很喜欢用min-height。这次为外部设置了min-height,使得内部子元素的百分比没生效,于是尝试解决。

情况

当时的情况有些复杂,我们用一段类似的代码来模拟这个情况。

<template>
  <main id="main">
    <div class="home">
      <span class="testText">测试文字</span>
    </div>
    <div>-------------模拟后面的元素</div>
  </main>
</template>

<style scoped>
#main {
  box-sizing: border-box;
  overflow: hidden;
  background-color: greenyellow;
  min-height: 100vh;
}
.home {
  box-sizing: border-box;
  height: 50%;
  background-color: red;
}
.testText {
  font-size: 2rem;
}
</style>

父容器设置min-height,子元素height百分比失效 / height: 100%失效尝试解决height: a

空白处是默认样式,不必关心,为了方便截图,我打开f12切换成了移动设备显示。

可以发现,home标签没有占据对应的百分比高度。

分析

说是分析其实也不太对,我看了一些别人的文章,原因如下:

我们通常认为子元素的高度百分比设置是基于父容器的高度的。但是这句话其实不对,子元素只是基于height,而不是实际高度,也就是说min-height对其造成不了影响。那么可以猜到,父容器#main只设置了min-height而没有设置height,那么height的值为auto,而auto的百分比是用不了的,于是百分比失效。

解决

解决之前,我们需要再次梳理一下自己的需求:

  1. 父容器高度不固定,且拥有最小高度(保底高度)
  2. 子元素需要使用百分比高度。(不一定是100%)
  3. 后面的元素要正常显示(位置正确)

这样一来,把父容器高度固定这条路就走不通了,放弃1去追求2无异于拆东墙补西墙。

那么有哪些解决方案呢?

绝对定位(错误版)

其实在尝试时,还出现了一些状况,由于我要测试非100%的情况,于是在home之后加了一个测试元素,然后试图使用padding-top来占用home本该占用的空间,使得测试元素的位置符合预期。 但是此时遇到了另一个问题,那就是,padding的百分比是基于自身宽度的,哪怕是top和bottom依然是基于宽度,这有些反直觉。

<template>
  <main id="main">
    <div class="home">
      <span class="testText">测试文字</span>
    </div>
    <div>-------------模拟后面的元素</div>
  </main>
</template>

<style scoped>
#main {
  /* 添加的代码 */
  position: relative;
  padding-top: 50%;

  box-sizing: border-box;
  overflow: hidden;
  background-color: greenyellow;
  min-height: 100vh;
}
.home {
  /* 添加的代码 */
  position: absolute;
  top: 0;
  left: 0;

  box-sizing: border-box;
  height: 50%;
  background-color: red;
}
.testText {
  font-size: 2rem;
}
</style>

效果如下,显然不是我们想要的。

父容器设置min-height,子元素height百分比失效 / height: 100%失效尝试解决height: a

绝对定位(正确版)

思路也很简单,既然绝对定位能够解决百分比问题,但是解决不了空间占用的问题,那么我们直接避开空间占用问题,使用程序设计中一种非常常见的操作——“套娃”。我们直接在home外部套一层wrapper,wrapper大小100%,然后home就能正常计算宽高了。

<template>
  <main id="main">
    <div class="wrapper">
      <div class="home">
        <span class="testText">测试文字</span>
      </div>
      <div>-------------模拟后面的元素</div>
    </div>
  </main>
</template>

<style scoped>
#main {
  /* 添加的代码 */
  position: relative;

  box-sizing: border-box;
  overflow: hidden;
  background-color: greenyellow;
  min-height: 100vh;
}
.wrapper {
  position: absolute;
  height: 100%;
  width: 100%;
}
.home {
  box-sizing: border-box;
  height: 50%;
  background-color: red;
}
.testText {
  font-size: 2rem;
}
</style>

效果如下

父容器设置min-height,子元素height百分比失效 / height: 100%失效尝试解决height: a

原理

绝对定位元素与普通元素的计算方式不同,简单来说就是,普通元素使用百分比时参考的并不是父级元素的实际高度,因此经常会失效(auto时)。

grid

grid容器默认情况下,倾向于让子元素占满其内部空间

<template>
  <main id="main">
    <div class="wrapper">
      <div class="home">
        <span class="testText">测试文字</span>
      </div>
      <div>-------------模拟后面的元素</div>
    </div>
  </main>
</template>

<style scoped>
#main {
  /* 添加的代码 */
  display: grid;

  box-sizing: border-box;
  overflow: hidden;
  background-color: greenyellow;
  min-height: 100vh;
}
.home {
  box-sizing: border-box;
  height: 50%;
  background-color: red;
}
.testText {
  font-size: 2rem;
}
</style>

flex的align-items: stretch;

flex: 1可以占满剩余空间。 flex的侧轴默认情况下为stetch,从而避开了使用百分比的问题。

如果给wrapper设置个百分比,反而会失效。

虽然我们避开了百分比,但是我们的子元素依然要使用百分比,于是按照相同的套路,我们开始套娃。

<template>
  <main id="main">
    <div class="wrapper">
      <div class="home">
        <span class="testText">测试文字</span>
      </div>
      <div>-------------模拟后面的元素</div>
    </div>
  </main>
</template>

<style scoped>
#main {
  /* 添加的代码 */
  display: flex;

  box-sizing: border-box;
  overflow: hidden;
  background-color: greenyellow;
  min-height: 100vh;
}
.wrapper {
  flex: 1;
}
.home {
  box-sizing: border-box;
  height: 50%;
  background-color: red;
}
.testText {
  font-size: 2rem;
}
</style>

结语

虽然遇到问题时多少有些懊恼,但是最终还是解决了,学到了新的东西还是很开心的。 这三种方式template部分基本相同,硬要说的话,grid方案的wrapper类名可以不写(但是html标签要保留)。 grid方案写起来是最简单的,可读性也是最差的;相比之下绝对定位的方案可读性是最好的但是也是最麻烦的。没有太过明显的优劣,喜欢哪个用哪个即可。

标题图片生成器

虽然不是我写的,但是用一用应该没什么问题。 logo.bluearchive.cc/

转载自:https://juejin.cn/post/7409138396792930338
评论
请登录