【问题标题】:restrict child div height to parent container height [duplicate]将子 div 高度限制为父容器高度 [重复]
【发布时间】:2021-03-19 12:11:39
【问题描述】:

我希望 graph div 的高度一直延伸到其父 (graph-container) 容器的末端,但不超过它。我已经尝试将 graph's 的高度设置为 100% 并继承,但是它们都导致它超出了它的父容器的底部边缘(我不想使用溢出:隐藏)。有没有办法在 graph 上设置 height 属性,以便自动将其高度设置为正确的值?

当前输出:

我想要的:

当前代码:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-size: 20px;
}

.wrapper {
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
}

.graph-container {
  border: 3px solid black;
  height: 60vh;
  width: 70vw;
  margin-top: 10vh;
}

.graph {
  height: 100%;
  width: 100%;
  border: 3px solid red;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="wrapper">
      <div class="graph-container">
        <h1>Graph Container</h1>
        <div class="graph">Graph</div>
      </div>
    </div>
  </body>
</html>

【问题讨论】:

    标签: javascript html css flexbox grid


    【解决方案1】:

    你看到的溢出是因为已经有一个元素占用了父元素的一些空间,所以height: 100%加上另一个元素的高度显然会超过父元素的高度。

    有不同的方法来解决这个问题。
    我推荐以下两种方式之一:

    但是,您也可以使用以下方式解决它们:

    CSS 弹性盒

    父级需要display: flexflex-direction: column 将其子级布置在一列中。

    应该长大占用剩余空间的孩子需要flex-grow: 1

    /* Ignore; only for displaying the example */
    * {
      margin: 0;
      font-size: 24px;
    }
    html, body {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .graph-container, .graph {
      border: 3px solid black;
      box-sizing: border-box;
    }
    
    /* The answer */
    .graph-container {
      height: 60vh;
      width: 70vw;
      
      display: flex;
      flex-flow: column; /* Shorthand for ('flex-direction' | 'flex-wrap') */
    }
    .graph {
      flex-grow: 1;
      border-color: red;
    }
    <div class="graph-container">
      <h1>Graph Container</h1>
      <div class="graph">Graph</div>
    </div>

    CSS 网格

    父母需要display: gridgrid-template-rows: auto 1fr

    grid-template-rows: auto 1fr 使第二个孩子占用在其他孩子获得各自未使用fr-unit 定义的空间后剩余的空间。
    在这里,&lt;h1&gt; 获得了它需要的空间,所有剩余空间都交给了.graph

    /* Ignore; only for displaying the example */
    * {
      margin: 0;
      font-size: 24px;
    }
    html, body {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .graph-container, .graph {
      border: 3px solid black;
      box-sizing: border-box;
    }
    
    /* The answer */
    .graph-container {
      height: 60vh;
      width: 70vw;
      
      display: grid;
      grid-template-rows: auto 1fr;
    }
    .graph {
      border-color: red;
    }
    <div class="graph-container">
      <h1>Graph Container</h1>
      <div class="graph">Graph</div>
    </div>

    CSS calc()

    font-sizeheight 的关系

    solution of sergey kuznetsov 一样,您可以猜到height(仅适用于小尺寸!)等于font-size

    这并不总是正确的,因为height 实际上取决于line-height,这又取决于当前使用的字体。

    问题,图解

    例如,对于给定字体,line-height 大约是 1.05- 比 font-size 高。由于浏览器无法显示小于 px-unit 的值,因此有效地截断了小数位。

    这使得该等式仅适用于 font-size 的小值,如下面的示例所示。
    示例(toInt() 去掉小数位):

    • toInt(20px of 'font-size' * 1.05) = 20px of 'height'
    • toInt(60px of 'font-size' * 1.05) = 63px of 'height'

    这意味着,虽然这有效(对于小的 font-size-values):
    calc(100% - 20px - 3px)20px 由于 font-size3px 由于 border-width

    /* Ignore; only for displaying the example */
    * {
      margin: 0;
      font-size: 24px;
    }
    html, body {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .graph-container, .graph {
      border: 3px solid black;
      box-sizing: border-box;
    }
    
    /* The answer */
    .graph-container {
      height: 60vh;
      width: 70vw;
    }
    h1 {
      font-size: 20px;
    }
    .graph {
      height: calc(100% - 20px - 3px);
      display: block;
      border-color: red;
    }
    <div class="graph-container">
      <h1>Title</h1>
      <div class="graph">Graph</div>
    </div>

    ...这不起作用(对于伟大的font-size-values):
    calc(100% - 60px - 3px)60px 由于font-size3px 由于border-width

    /* Ignore; only for displaying the example */
    * {
      margin: 0;
      font-size: 24px;
    }
    html, body {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .graph-container, .graph {
      border: 3px solid black;
      box-sizing: border-box;
    }
    
    /* The answer */
    .graph-container {
      height: 60vh;
      width: 70vw;
    }
    h1 {
      font-size: 60px;
    }
    .graph {
      height: calc(100% - 60px - 3px);
      display: block;
      border-color: red;
    }
    <div class="graph-container">
      <h1>Title</h1>
      <div class="graph">Graph</div>
    </div>

    这就是为什么最好实际定义height-property 本身而不是依赖font-sizeline-heightheight 相同(显然并非总是如此)。这让我们...

    使用 CSS 自定义属性

    您使用calc(100% - TITLE_HEIGHT) 将第二个孩子的高度设置为剩余空间,其中TITLE_HEIGHT 是另一个孩子的高度&lt;h1&gt;

    我们可以使用CSS Custom properties 设置高度以减少“幻数”的数量,这使得以后重构代码更容易,也许已经更容易阅读了。
    我使用--title-height 作为高度。

    自定义属性只能在元素本身及其子元素中访问,这意味着我们需要在其父元素.graph-container 中定义它。

    现在我们可以像这样使用var() 解析--title-height 的值:
    var(--title-height)

    /* Ignore; only for displaying the example */
    * {
      margin: 0;
      font-size: 24px;
    }
    html, body {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .graph-container, .graph {
      border: 3px solid black;
      box-sizing: border-box;
    }
    
    /* The answer */
    .graph-container {
      --title-height: 26px;
      
      height: 60vh;
      width: 70vw;
      
      display: block;
    }
    h1 {
      height: var(--title-height);
    }
    .graph {
      height: calc(100% - var(--title-height));
      display: block;
      border-color: red;
    }
    <div class="graph-container">
      <h1>Graph Container</h1>
      <div class="graph">Graph</div>
    </div>

    JavaScript

    在使用JS时,我们需要设置父元素的高度以及&lt;h1&gt;-元素的高度,并计算.graph的剩余高度。剩余高度可以使用Element.style.height设置为.graph的高度。

    /* The answer */
    var container = document.querySelector('.graph-container');
    var title = document.querySelector('h1');
    var graph = document.querySelector('.graph');
    
    var remainingHeight = container.clientHeight - title.clientHeight;
    graph.style.height = remainingHeight + "px"; // Make sure it is of unit "px"
    /* Ignore; only for displaying the example */
    * {
      margin: 0;
      font-size: 24px;
    }
    html, body {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .graph-container, .graph {
      border: 3px solid black;
      box-sizing: border-box;
    }
    
    .graph-container {
      height: 60vh;
      width: 70vw;
    }
    .graph {
      border-color: red;
      display: block;
    }
    <div class="graph-container">
      <h1>Graph Container</h1>
      <div class="graph">Graph</div>
    </div>

    这种方法的问题是,一旦找到高度就会固定。这将使.graph 没有响应。为了实现.graph 是响应式的,我们需要观察父级是否使用ResizeObserver 调整了大小。

    每次父级调整大小时,重新计算.graph的大小。

    /* The answer */
    var container = document.querySelector('.graph-container');
    var title = document.querySelector('h1');
    var graph = document.querySelector('.graph');
    
    new ResizeObserver(() => {
      graph.style.height = container.clientHeight - title.clientHeight + "px";
    }).observe(container);
    /* Ignore; only for displaying the example */
    * {
      margin: 0;
      font-size: 24px;
    }
    html, body {
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .graph-container, .graph {
      border: 3px solid black;
      box-sizing: border-box;
    }
    
    .graph-container {
      height: 60vh;
      width: 70vw;
    }
    .graph {
      border-color: red;
      display: block;
    }
    <div class="graph-container">
      <h1>Graph Container</h1>
      <div class="graph">Graph</div>
    </div>

    【讨论】:

      【解决方案2】:

      我还想建议使用calc() 的解决方案。即:

      height: calc(100% - 23px);
      

      其中 23px 是 h1 标记 (font-size: 20px),而边框 graph 类是 3 像素 (border: 3px solid red)。

      在此示例中,子 div 的高度将整齐地放在父 div 内。

      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        font-size: 20px;
      }
      
      .wrapper {
        height: 100vh;
        width: 100vw;
        display: flex;
        justify-content: center;
      }
      
      .graph-container {
        border: 3px solid black;
        height: 60vh;
        width: 70vw;
        margin-top: 10vh;
      }
      
      .graph {
        height: calc(100% - 23px);
        width: 100%;
        border: 3px solid red;
      }
      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <title>Document</title>
          <link rel="stylesheet" href="style.css" />
        </head>
        <body>
          <div class="wrapper">
            <div class="graph-container">
              <h1>Graph Container</h1>
              <div class="graph">Graph</div>
            </div>
          </div>
        </body>
      </html>

      【讨论】:

      • 请注意font-size 不等于line-height。对于更大的font-sizes,实际元素高度会有所不同。 line-height 取决于所使用的字体,并且默认情况下(至少在我认为的 chrome 中)大约是 1.027-倍于 font-size。然而,height 不能达到一个像素高的分数,因此小数位被“截断”,使其看起来像 20px of 'font-size' = 20px of 'height' 而实际上是 floor(20px of 'font-size' * 1.027) = 20px of 'height',其中 floor() “截断”小数位。
      • @OskarGrosser,是的,我知道。在这种情况下,line-height 没有应用,所以我给出了这个解决方案。
      • 好吧,是的,你是绝对正确的,这是一个可行的解决方案。但是,至少要提到这可能会成为更大字体大小的问题。
      • @OskarGrosser,谢谢,但您的解决方案是最好的! :)
      • 我在回答中添加了一个关于我们“讨论”的小节。你可以编辑它,以防你有什么要添加的。
      猜你喜欢
      • 2012-07-29
      • 2014-04-22
      • 1970-01-01
      • 1970-01-01
      • 2011-01-11
      • 1970-01-01
      • 2012-06-07
      • 1970-01-01
      相关资源
      最近更新 更多