在保持比例的同时填充父级 div

13
我希望有一个div区域,尽可能填满其父元素并保持比例。
渲染结果如下: enter image description here 目前我的做法是:

html,
body {
  height: 100%;
}

.parent {
  /* Parent's height and width are unknown,
     it could be dynamic, e.g. parent is part of a flex layout. */
  height: 80%;
  width: 90%;
  border-style: solid;
  border-width: 2px;
  border-color: black;
}

.child {
  width: 90vw;
  /* 90% of viewport vidth */
  height: 50.625vw;
  /* ratio = 9/16 * 90 = 50.625 */
  max-height: 90vh;
  max-width: 160vh;
  /* 16/9 * 90 = 160 */
  margin: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: #A0522D;
}
<div class="parent">
  <div class="child">
    content that is not images...
  </div>
</div>

这个 CSS 的效果与我的期望一致,但是它使用了视口而非父元素 div,在实际情况中可能会出现问题。

我正在寻找一种基于父元素 div 来填充的方法。


使用90%和50.625%使子div只是跟随父div而不保持其比例。 - Joris La Cancellera
尝试更改“child”的position: relative;并删除顶部,底部,左侧和右侧定位。对于边距,您可能也要将其删除,除非您需要水平居中,然后使用margin 0 auto;。我现在有一些测试代码,父div为40%,子div为80%,它可以工作,并且我已经尝试了几个不同的百分比。除了这些更改之外,没有其他区别。 - Krik
我认为我需要说一下,如果您想要一个浏览器无关的解决方案来解决这个确切的行为问题,迟早您将不得不采用JavaScript解决方案。 这是一个交叉引用的双未知数方程问题,即使您采用脚本解决方案,最终解决起来也会造成一些困扰。 - Bekim Bacaj
@JorisLaCancellera 只需将 position: relative 应用于 .parent,然后您就可以在 .child 的尺寸中使用 %。我也是这样做的,它有效。 - ac_mmi
1
请返回已翻译的文本。 - Temani Afif
显示剩余5条评论
4个回答

11
使用 aspect-ratio: 16 / 9; overflow: hidden;aspect-ratio MDN文档)应该可以给您需要的精确结果,无需使用填充技巧。请确保父元素设置为 display: grid,否则可能无法正常缩放。 aspect-ratio CSS属性获得了所有主流浏览器 (caniuse.com) 的支持,但Safari目前还未支持, 不过计划于今年内添加支持。这是实现此效果的最佳/正确方式,而无需诉诸JavaScript或任何hack解决方案。
Stack Overflow上的相关问题和答案如下: 以下是我的解决方法示例:

html, body { height: 100%; }

.parent {
  display: grid;
  resize: both;
  height: 50%;
  width: 90%;
  border: 2px solid #000;
  overflow: hidden;
}

.child {
  width: 100%;
  max-height: 100%;
  margin: auto;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  box-sizing: border-box;
  position: relative;
  background: #a0522d;
  text-align: center;
  font-size: 20px;
  color: white;
  /* using the below to center the text, optional */
  display: flex;
  align-items: center;
  justify-content: center;
}
<div style="padding: 5px 10px; margin-bottom: 10px; background: #f00; color: #fff; text-align: center; z-index: 1;">Resize the block below using the resize controls to see this in action.</div>
<div class="parent">
  <div class="child">content that is not images...</div>
</div>


1
@QuentinRoy 我刚刚发布了我的解决方案,我相信它正是你所寻找的。有时间请看一下。除了Safari浏览器外,所有主流浏览器都支持aspect-ratio CSS属性,不过Safari计划在今年添加支持。这是实现此效果的最佳方法,无需使用JavaScript或任何hack解决方案。 - Brandon McConnell
1
谢谢!我不知道aspect-ratio属性。不幸的是,我不能在Safari中使用它,但我迫不及待地希望它能被广泛应用。我相信这是唯一的方法。 - Quentin Roy
1
@BrandonMcConnell 在 Firefox 93 中,当我点击“运行代码片段”时,它的显示效果是这样的:https://i.imgur.com/MQkJ0FL.png。然而,我刚刚在 Edge 中尝试了一下,它在那里的显示效果是正确的。根据 MDN 的说法,自 Firefox 版本 89 起,Firefox 完全支持 aspect-ratio,所以我不确定为什么会出现这种差异。 - mrossman
@BrandonMcConnell 感谢您提供了 aspect-ratio 输入,非常好。@mrossman 也遇到了同样的问题。您解决了吗? - Kaan
1
似乎“overflow: hidden”技巧不再起作用了(Safari,Firefox,Chrome v103+)。 - tavoyne
显示剩余3条评论

0
使用flexbox和padding。使用媒体查询来确定视口的最小纵横比,然后进行相应的调整。

html,
body {
  height: 100%;
}

.parent {
  height: 100%;
  width: 100%;
  border-style: solid;
  border-width: 2px;
  border-color: black;
  /* to center */
  display: flex;
  align-items: center;
  justify-content: center;
}

.child {
  width: 100vw;
  /* 16:9 aspect ratio = 9 / 16 = 0.5625 = padding-bottom*/
  padding-bottom: 56.25%;
  background: #A0522D;
}

@media (min-aspect-ratio: 16/9) {
  .child {
    height: 100vh;
    /*16:9 aspect ratio = 9 / 16 = 177.77 = width*/
    width: 177.77vh;
    padding: 0;
    margin: 0px;
    background: red;
  }
}
<div class="parent">
  <!-- the viewbox will provide the desired aspect ratio -->
  <div class="child">
    content that is not images...
  </div>
</div>

这是一个演示

谢谢!这是一个好技巧。然而,孩子们只适应宽度,而不是高度。调整宽度和高度是我无法在没有JS的情况下解决的棘手问题。 - Quentin Roy
@QuentinRoy,这个怎么样?我使用媒体查询来检查视口的宽高比。当比例至少为16:9时,它会自动调整到高度。无需JavaScript。 - Prosy Arceno
谢谢!但现在子元素依赖于视口。如果父元素不是body的大小呢?如果它只是页面上的任何其他组件呢?例如,如果它是flex布局的一部分(参见示例),那么它的大小通常会取决于其兄弟元素。 - Quentin Roy
@QuentinRoy,我猜你已经通过js解决了这个问题。你具体在寻找什么样的解决方案? - Prosy Arceno
@QuentinRoy 我将位置分配给父容器,这将使子元素相对于父元素绝对定位。我也做了同样的事情,它起作用了,你可以看到代码。 - ac_mmi

0
也许可以加上绝对定位,通过将上、右、下、左设置为0并使用margin:auto来使其正常工作。您也可以使用flex居中或使用left 50%和transform -50%的绝对定位。

body {
            padding: 0;
            margin: 0;
            height: 100vh;
            width: 100vh;
           

        }

        .child {
            width: 90vw;
            /* 90% of viewport vidth */
            height: 50.625vw;
            max-height: 90vh;
            max-width: 160vh;
            /* Adding this maybe min-width and min-height */
            min-height: 90vh;
            min-width: 160vh;
            
            /* 16/9 * 90 = 160 */
            background: #f7f7f7;
            box-shadow: 0px 5px 30px 0px rgba(0, 0, 0, 0.18);
            border-radius: 4px;
            margin: auto;
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
        }
<!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>Parent Child</title>
</head>

<body>  <!-- parent -->
    <div class="child"></div>
</body>

</html>


这很好,但子元素不取决于父元素的大小,而是取决于视口的大小。 - Quentin Roy
1
是的,但我的问题在于通常您无法控制父元素的尺寸。在我的情况下,父元素是弹性布局的一部分。 - Quentin Roy
是的,我明白你的意思,但不是完全明白。如果你能提供一个像你之前提供图片和数字那样的例子,并且指定父元素的最大和最小高度和宽度,那将非常有帮助。你也可以使用calc函数。 - Younes Keraressi
1
Joris的绘画完美地展现了我们所追求的东西。 - Quentin Roy
通过为子元素添加min-width和min-height,子元素将强制其大小适应任何变小的父元素,除此之外无法实现。 - Younes Keraressi
显示剩余7条评论

0
为了使子元素的尺寸依赖于父容器设置,需要在父容器中设置position:relative
通常情况下,当我们将一个元素设置为position:absolute时,它会相对于初始包含块(即<body>)定位,除非给定任何其他最近的父容器的位置不是静态的(默认情况下)。因此,通过给父容器设置相对位置,我们将.child元素相对于先前相对于文档或主体定位的.parent元素定位。
这对您有用。

html,
body {
  height: 100%;
}

.parent {
  /* Parent's height and width are unknown,
     it could be dynamic, e.g. parent is part of a flex layout. */
  position:relative;
  height: 80%;
  width: 90%;
  border-style: solid;
  border-width: 2px;
  border-color: black;
}

.child {
  width: 90%;
  /* 90% of viewport vidth */
  height: 50.625%;
  /* ratio = 9/16 * 90 = 50.625 */
  max-height: 90%;
  max-width: 160%;
  /* 16/9 * 90 = 160 */
  margin: auto;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: #A0522D;
}
<div class="parent">
  <div class="child">
    content that is not images...
  </div>
</div>


1
谢谢!但是这不能保持宽高比。 - Quentin Roy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接