4

I have a headerbar with the usual content. App-Logo, nav, some controls.

The navbar's height is not set, but determined by its contents. It is a flex container.

Now I want the App-Logo to stretch to the vertical available space and maintain its aspect ratio.

Here is what it should look like:

Navbar Goal

Here is the code which achieves the image above:

.headerbar {
  display: flex;
  align-items: stretch;
  gap: 1rem;
  padding: .5rem;
  background: #f0f0f0;
  border-bottom: 1px solid gray;
}

.logo {
  aspect-ratio: 1 / 1; /* Not working */

  border-radius: 5px;
  background: radial-gradient(circle, rgba(63, 94, 251, 1) 0%, rgba(252, 70, 107, 1) 100%);
}
<div class="headerbar">
  <div class="logo"></div>
  <p>Link 1</p>
  <p>Link 2</p>
  <p>Link 3</p>
</div>

Link to code: https://jsfiddle.net/v2ta54eg/19/

As you can see, the logo is not visible. It seems to only stretch itself, as expected, but the aspect-ratio property has no effect on the width. The width stays 0.

What tried to do, was use aspect-ratio: 1 / 1 and I expected it to set the width to the same amount as the height. This is because the height is kind of set with aling-self: stretch.

So the question is:

How can I make a div have the same width as height, taking the height from the flex parent align-items: stretch / align-self: stretch?

Chiff Shinz
  • 377
  • 2
  • 14
  • I don't think this is possible with only css - the only way to get your width matching your height is by using `aspect-ratio`, but then your element will become a replaced element and flex has an issue with them: https://jsfiddle.net/7z5ghLn2/ – Pete Aug 31 '23 at 12:28

4 Answers4

1

You can definitely do this with a little extra HTML:

article {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
}

.headerbar {
  display: flex;
  padding: .5rem;
  background: #f0f0f0;
  border-bottom: 1px solid gray;
}

.logo {
  aspect-ratio: 1;
  height: 100%;
  border-radius: 5px;
  background: radial-gradient(circle, rgba(63, 94, 251, 1) 0%, rgba(252, 70, 107, 1) 100%);
}

.links {
  display: flex;
  gap: 1em;
  padding: 10px;
  flex: 1 0 0;
}
<article>
  <div class="headerbar">
    <div class="logo">
    </div>
    <div class="links">
      <p>Link 1</p>
      <p>Link 2</p>
      <p>Link 3</p>
    </div>
  </div>
</article>
ralph.m
  • 13,468
  • 3
  • 23
  • 30
  • Thank you. This seems to work! Could you maybe explain a bit why this works? – Chiff Shinz Aug 31 '23 at 14:41
  • Hah, I wish I could. I was trying to do something similar with an image recently, and it worked well without the extra wrapper but only on Chrome-based browsers. Flexbox and Grid do have powers in some circumstances to understand their container height without it being specified, which is why the `height: 100%` can work here, where it wouldn't have in the past. It is odd that your original didn't work, given that the div is stretching full height. Here's that similar example I was talking about: https://stackoverflow.com/questions/76904694/square-div-based-on-its-neighbour/76905006#76905006 – ralph.m Aug 31 '23 at 22:47
1

You will have better luck using CSS grid instead

.headerbar {
  display: grid;
  grid-auto-flow: column; /* column flow */
  grid-template-rows: 1fr; /* set a height to rows */
  justify-content: start; /* align to left */
  gap: 1rem;
  padding: .5rem;
  background: #f0f0f0;
  border-bottom: 1px solid gray;
}

.logo {
  height: 100%;
  aspect-ratio: 1;
  border-radius: 5px;
  background: radial-gradient(circle, rgba(63, 94, 251, 1) 0%, rgba(252, 70, 107, 1) 100%);
}
<div class="headerbar">
  <div class="logo"></div>
  <p>Link 1</p>
  <p>Link 2</p>
  <p>Link 3</p>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
0

Remove withd add these two values to the .logo

.logo {
    aspect-ratio: 1/1; /*aspect ratio 1:1 (width/height) */
    flex: 0 0 auto; /* Prevent the logo from growing or shrinking */
}
Yugerten
  • 244
  • 3
  • 13
  • Okay, the `flex: 0 0 auto;` is interesting. I tried it, but it still doesn't work. Here's the fiddle: https://jsfiddle.net/v2ta54eg/19/ – Chiff Shinz Aug 31 '23 at 11:59
0

align-items: stretch is not a height, or any other unit of length. It's just a command that tells flex items to consume available space.

aspect-ratio is not working because it doesn't have enough to go on.

If you add height to the container, it will work.

.headerbar {
  display: flex;
  gap: 1rem;
  padding: .5rem;
  background: #f0f0f0;
  border-bottom: 1px solid gray;
  height: 150px; /* NEW */
}

.logo {
  aspect-ratio: 1/1;
  flex: 0 0 auto;
  border-radius:5px;
  background: radial-gradient(circle, rgba(63, 94, 251, 1) 0%, rgba(252, 70, 107, 1) 100%);
}
<html>
  <div class="headerbar">
    <div class="logo"></div>
    <p>Link 1</p>
    <p>Link 2</p>
    <p>Link 3</p>
  </div>
</html>

OR, if you add width to the items, it will work:

.headerbar {
  display: flex;
  gap: 1rem;
  padding: .5rem;
  background: #f0f0f0;
  border-bottom: 1px solid gray;
}

.logo {
  aspect-ratio: 1/1;
  flex: 0 0 150px; /* modified */
  border-radius:5px;
  background: radial-gradient(circle, rgba(63, 94, 251, 1) 0%, rgba(252, 70, 107, 1) 100%);
}
<html>
  <div class="headerbar">
    <div class="logo"></div>
    <p>Link 1</p>
    <p>Link 2</p>
    <p>Link 3</p>
  </div>
</html>

But, it won't work with just width: auto (i.e., flex-basis: auto).

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701