Div在动态计算高度时未保持1/1的宽高比。

huangapple go评论66阅读模式
英文:

Div not maintaining a 1/1 aspect ratio when height is calculated dynamically

问题

我试图使用 flexbox 创建以下 CSS 布局:

假设布局是一个 flex 行,左侧有一个框(图像),右侧是一个 flex 列,所有文本都堆叠在一起。左侧框的高度自动缩放为右侧 flex 列的高度。到目前为止,我已经做到了这一点,但我无法使其成为一个正方形形状(宽度与高度相同)。

目前我有以下代码产生以下结果:

.container {
  background: orange;
  display: flex;
  flex-direction: row;
}

.profile_pic {
  aspect-ratio: 1/1;
  background: blue;
}

.text_container {
  display: flex;
  flex-direction: column;
}
<div class="container">
  <div class="profile_pic"></div>

  <div class="text_container">
    <h1>Name: Toby</h1>
    <h2>Gender: Male</h2>
    <h3>Password: 123</h3>
  </div>
</div>

应该在列的左侧有一个正方形的蓝色框,但出现了某种原因没有显示?

如果我设置一个特定的宽度,它会显示,但这不是我想要的,因为我希望宽度与高度相同(保持 1/1 的纵横比)。

我目前的“解决方法”是将蓝色框包装在一个具有 align-items 设置为 center 的 flex 中,然后使蓝色框的大小硬编码,大致匹配框的高度:

我看到许多类似的布局,例如 YouTube 频道的布局、Stack Overflow 的指示器等。我相信这些类似的布局是通过设置容器或图像本身的显式高度等解决方法来实现的。这种方法不太好,因为总会存在一些误差,而且如果我想从右侧的列中删除一行,我将需要手动调整大小(这不是动态的)。

英文:

I'm trying to create the following CSS layout using flexbox:

Div在动态计算高度时未保持1/1的宽高比。

Imagine the layout as a flex row, with one box on the left (the image) and to the right a flex column with all the text stacked on top of each other. The height of the box on the left automatically scaled to the height of the flex column to the right. I have gone up to this point so far, but I have been unable to get it into a square shape (as in the width is the same as the height).

Currently I have the code which produces the following result:

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-css -->

.container {
  background: orange;
  display: flex;
  flex-direction: row;
}

.profile_pic {
  aspect-ratio: 1/1;
  background: blue;
}

.text_container {
  display: flex;
  flex-direction: column;
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;profile_pic&quot;&gt;&lt;/div&gt;

  &lt;div class=&quot;text_container&quot;&gt;
    &lt;h1&gt;Name: Toby&lt;/h1&gt;
    &lt;h2&gt;Gender: Male&lt;/h2&gt;
    &lt;h3&gt;Password: 123&lt;/h2&gt;
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

Div在动态计算高度时未保持1/1的宽高比。

There is meant to be a square shaped blue box on the left of column which contains the text but it's not showing for some reason?

If I set a specific width, it does show, but this is not what I want as I wish for the width to be the same as the height (maintain a 1/1 aspect ratio):

Div在动态计算高度时未保持1/1的宽高比。

My current 'workaround' is wrapping the blue box in a flex with align-items set to center, and then making the blue box a hard coded size which roughly matches the height of the box:

Div在动态计算高度时未保持1/1的宽高比。

I see lots of such similar layouts, for example the YouTube channel thing:

Div在动态计算高度时未保持1/1的宽高比。

Stack Overflow indicator:

Div在动态计算高度时未保持1/1的宽高比。

I believe such similar layouts are done by using workarounds such as setting an explicit height for the container or the image itself. This approach isn't fine as there is always a small margin of error, and if I want to remove a line from the column flex to the right, I will need to manually adjust the sizes (it's not dynamic).

答案1

得分: 3

花了我几个小时,我以为这应该很简单,但我没能更早地找到解决方案。所以在调整了弹性盒子、相对绝对定位甚至表格布局之后,我才意识到我们可以使用网格来实现这个效果。这里最重要的是第一个子元素上的 min-height: 100%height: 0height 必须为零,以防止它参与网格高度计算,而 min-height 则是为了使其占据整行高度的 100%:

.container {
  background: orange;
  display: grid;
  grid-template-columns: auto 1fr;
}

.profile_pic {
  min-height: 100%;
  height: 0;
  background: blue;
}

img {
  max-width: 100%;
  height: 100%;
  aspect-ratio: 1/1;
}

.text_container {
  display: flex;
  flex-direction: column;
}
<div class="container">
  <div class="profile_pic">
    <img src="https://placehold.co/2">
  </div>

  <div class="text_container">
    <h1>Name: Toby</h1>
    <h2>Gender: Male</h2>
    <h3>Password: 123</h3>
  </div>
  <div>

你可以将图像更改为非1/1比例的内容,你会发现它仍然保持1/1的比例。

英文:

It took me hours for this, I just thought it's supposed to be simple but I couldn't find the solution sooner. So after tweaking with flexbox, relative-absolute position, and even table layout, I just realized that we can use grid instead to achieve this. The most important thing in here is the min-height: 100% and height: 0 on the first child. The height must be zero so that it's prevented from the grid height calculation, and the min-height is so that it's 100% of row's height:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

.container {
  background: orange;
  display: grid;
  grid-template-columns: auto 1fr;
}

.profile_pic {
  min-height: 100%;
  height: 0;
  background: blue;
}

img {
  max-width: 100%;
  height: 100%;
  aspect-ratio: 1/1;
}

.text_container {
  display: flex;
  flex-direction: column;
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;profile_pic&quot;&gt;
    &lt;img src=&quot;https://placehold.co/2&quot;&gt;
  &lt;/div&gt;

  &lt;div class=&quot;text_container&quot;&gt;
    &lt;h1&gt;Name: Toby&lt;/h1&gt;
    &lt;h2&gt;Gender: Male&lt;/h2&gt;
    &lt;h3&gt;Password: 123&lt;/h3&gt;
  &lt;/div&gt;
  &lt;div&gt;

<!-- end snippet -->

You can change the image to something with a not 1/1 ratio, and you'll see that it will stay in 1/1 ratio.

答案2

得分: 1

我不认为这可以通过CSS来解决,如果你想在高度方面尽可能灵活的话。但是几行JavaScript代码可以完成这个任务。首先确定外部容器的height。然后将接收到的值分配为图像容器的width

分配一个ID给每个元素可能会有一些优势,而不是使用类,但只有提供的代码,我不能确定。然而,你将不得不使用document.getElementById()而不是document.querySelector()

还应该提到,height可以根据要求以不同的方式确定:

clientHeight - 高度 + padding (当前正在使用)
offsetHeight - 高度 + padding + 边框

还有其他方法,但现在可能会太多了。

以下是代码片段...

let containerHeight = document.querySelector('.container').clientHeight;
let imgContainerWidth = document.querySelector('.profile_pic');
imgContainerWidth.style.width = containerHeight + 'px';
.container {
    display: flex;
    flex-direction: row;
    background: orange;
}

.profile_pic {
    margin-right: 30px;
    background: blue;
}

.text_container {
    display: flex;
    flex-direction: column;
}
<div class="container">
    <div class="profile_pic"></div>
    <div class="text_container">
        <h1>Name: Toby</h1>
        <h2>Gender: Male</h2>
        <h3>Password: 123</h3>
    </div>
<div>
英文:

I don't think this can be solved with CSS if you want to be as flexible as possible with regard to the height. But a few lines of JavaScript can do the job. First determine the height of the outer container. Then assign the received value as width to the image container.

It might be an advantage to assign an ID to each element instead of working with classes, but just with the provided code I can't say that. However, you would then have to use document.getElementById() instead of document.querySelector().

It should also be mentioned that height can be determined differently, depending on requirements:

clientHeight - height + padding (currently in use)
offsetHeight - height + padding + border

And others, but that would be too much for now.
Here's the snippet ...

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let containerHeight = document.querySelector(&#39;.container&#39;).clientHeight;
let imgContainerWidth = document.querySelector(&#39;.profile_pic&#39;);
imgContainerWidth.style.width = containerHeight + &#39;px&#39;;

<!-- language: lang-css -->

.container {
    display: flex;
    flex-direction: row;
    background: orange;
}

.profile_pic {
    margin-right: 30px;
    background: blue;
}

.text_container {
    display: flex;
    flex-direction: column;
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
    &lt;div class=&quot;profile_pic&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;text_container&quot;&gt;
        &lt;h1&gt;Name: Toby&lt;/h1&gt;
        &lt;h2&gt;Gender: Male&lt;/h2&gt;
        &lt;h3&gt;Password: 123&lt;/h2&gt;
    &lt;/div&gt;
&lt;div&gt;

<!-- end snippet -->

答案3

得分: 0

.profile_pic { writing-mode: vertical-lr; } 可以设置为一个选项。.container 必须具有 display: grid;

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  background: orange;
  display: grid;
  grid-template-columns: auto 1fr;
}

.profile_pic {
  aspect-ratio: 1;
  background: blue;
  writing-mode: vertical-lr;
  position: relative;
}

.profile_pic img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.text_container {
  display: flex;
  flex-direction: column;
}
<div class="container">
  <div class="profile_pic">
    <img src="https://picsum.photos/300/300">
  </div>
  <div class="text_container">
    <h1>Name: Toby</h1>
    <h2>Gender: Male</h2>
    <h3>Password: 123</h3>
  </div>
</div>
英文:

Also, as an option, you can set .profile_pic { writing-mode: vertical-lr; }. .container must have display: grid;:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-css -->

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  background: orange;
  display: grid;
  grid-template-columns: auto 1fr;
}

.profile_pic {
  aspect-ratio: 1;
  background: blue;
  writing-mode: vertical-lr;
  position: relative;
}

.profile_pic img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.text_container {
  display: flex;
  flex-direction: column;
}

<!-- language: lang-html -->

&lt;div class=&quot;container&quot;&gt;
  &lt;div class=&quot;profile_pic&quot;&gt;
    &lt;img src=&quot;https://picsum.photos/300/300&quot;&gt;
  &lt;/div&gt;
  &lt;div class=&quot;text_container&quot;&gt;
    &lt;h1&gt;Name: Toby&lt;/h1&gt;
    &lt;h2&gt;Gender: Male&lt;/h2&gt;
    &lt;h3&gt;Password: 123&lt;/h2&gt;
  &lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

答案4

得分: -2

Sure, here's the translated code portion:

<!-- 开始代码段:不隐藏,控制台:显示,Babel:不使用 -->

<!-- 语言:HTML -->

.container {
  background: orange;
  display: flex;
  flex-direction: row;
  height: 300px;
  align-items: center;
}

.profile_pic {
  aspect-ratio: 1/1;
  background: blue;
  height: 100%;
}

.text_container {
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  height: 100%;
}

<!-- 结束代码段 -->

You can try this out. In this code, you need to define a height value in the parent container.

英文:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

.container {
  background: orange;
  display: flex;
  flex-direction: row;
  height: 300px;
  align-items: center;
}

.profile_pic {
  aspect-ratio: 1/1;
  background: blue;
  height: 100%;

}

.text_container {
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
height: 100%;
  
}

<!-- end snippet -->

Try this out. In here you have to define a height value in the parent container.

huangapple
  • 本文由 发表于 2023年5月25日 08:23:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76328161.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定