0

Base scenario:

<div class="flex">
  <div id="avatar" />
  <div id="info"/>
</div>

Assuming info will have a dynamic height, based on its content, how can we make avatar be always square?

example 1

In the first example, info has 160px height, so avatar is a 160x160 square. In the second example, info has more content and its height is 305px, same applies to the avatar

Is there a css-only solution?

I was playing with Tailwind: https://play.tailwindcss.com/5ooxVe8F7E, but the green div in this link should have the same height as the red one.

Falci
  • 1,823
  • 4
  • 29
  • 54
  • Does this answer your question? [css grid of squares with flexbox](https://stackoverflow.com/questions/29307971/css-grid-of-squares-with-flexbox) – 0stone0 Aug 15 '23 at 09:32
  • `aspect-ratio` is definitely helpful here, @ostone0, but it doesn't supply the whole solution in this case. – ralph.m Aug 15 '23 at 10:30

2 Answers2

2

There are various ways to do this. Here's one:

article {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: 1fr;
  padding: 40px;
}

.avatar {
  aspect-ratio: 1;
  position: relative;
}

.info {
  background: rgb(170, 108, 108);
}

img {
  position: absolute;
  width: 100%;
}

body {
  background: #30353b;
}
<article>
  <div class="avatar">
    <img src="https://picsum.photos/id/1012/600/600">
  </div>
  <div class="info">
    info<br />
    info<br />
    info<br />
    info<br />
    info<br />
    info
  </div>
</article>

UPDATE

Unfortunately, the demo above only seems to work in Chrome-based browsers (such as Chrome, Edge, Brave). For other browsers, an extra wrapping div is needed:

const button = document.querySelector(".button");
function addPara() {
  const content = document.querySelector('.info');
  content.innerHTML += `<p>Paragraph ${content.childElementCount + 1}</p>`;
}
button.addEventListener("click", addPara, false);
article {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
}

.avatar {
  aspect-ratio: 1;
  position: relative;
  height:100%;
}

img {
  position: absolute;
  height: 100%;
}

/* extra styles  */

article {
  margin: 40px;
  position: relative;
  background-color: #d61be6;
}

.content {
  display: flex;
}

.info {
  padding: 10px;
  flex: 1 0 0;
  background: rgb(170, 108, 108);
}

body {
  background: #30353b;
}

p {
  margin: 0 0 5px;
  color: white;
}

button {
  position: absolute;
  top: 10px;
  right: 10px;
  border: none;
  padding: 4px 8px;
  border-radius: 5px;
}
<article>
  <div class="content">
    <div class="avatar">
      <img src="https://picsum.photos/id/1012/600/600">
    </div>
    <div class="info">
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
      <p>Paragraph 3</p>
    </div>
  </div>
  <button class="button">Add Text</button>
</article>

Click the Add Text button to watch what happens as the text grows.

ralph.m
  • 13,468
  • 3
  • 23
  • 30
0

in display:flex with flex-direction:row the height of your flex items are calculated based on the largest flex-item, so when you apply height:305px to info , comparing info with avatar which has 160px height, info now is taller and larger than the avatar, so it applies 305px height to avatar because it is the largest flex-item.

one solution to retrieve avatar content height is to set its height based on %, like height:60% or height:100% (the number doesn't matter and the unit is important) then avatar will retrieve its content and original height.