10

I have a card of sorts. On the right side of it is variable width/height content, and the left side is an image. I'd like the image to stretch vertically, taking up all of the vertical space in the card, and maintain an aspect ratio of 1/1 (so basically match its width to its height).

Is this possible without scripting it?

I was hoping the new aspect-ratio CSS property would come in handy, but it doesn't seem to take any effect without an explicit width/height, and setting the height to 100% ends up decreasing the height in order to arrive at 1/1 aspect-ratio, instead of increasing the width.

#container {
  background: lightgray;
  display: flex;
  justify-content: center;
  align-items: center;
}

#object {
  background: pink;
  aspect-ratio: 1/1;
  overflow: hidden;
  align-self:stretch;
}

#control {
  font-size:1.5em;
}
<div id="container" class="resizable">
  <div id="object"> 
    maintain 1/1
  </div>
  <div id="control">
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
  </div>
</div>
McKinley
  • 1,123
  • 1
  • 8
  • 18
noob0909
  • 101
  • 2

1 Answers1

1

Wow, this is a tricky one! But yes, I’ve found a way to do it in CSS.

As you found, aspect-ratio doesn’t seem to work to make a vertically-stretched flex child <div> as wide as it is high. So I tried using a small 1:1 <img> as the flex child, hoping that the intrinsic aspect-ratio of the image would cause the width to stretch proportionally with the height. That didn’t work — it only stretched vertically. However, switching from flex to grid helped in that department. So step 1 gets us a square box on the left which matches the height of the content on the right. Here is a snippet to demonstrate.

.card {
  background: lightgray;
  display: inline-grid;
  grid-template-columns: auto auto;
  gap: 1em;
  border: 1px solid #aaa;
  box-shadow: 0 0 1em rgb(0,0,0,0.3);
  margin: 2em;
}

.intrinsic-1x1 {
  align-self: stretch;
}

.content {
  font-size: 1.5em;
}
<div class="card">
  <img class="intrinsic-1x1" src="https://donald.net.au/bugs/1x1-tiny.png">
  <div class="content">
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
  </div>
</div>

<div class="card">
  <img class="intrinsic-1x1" src="https://donald.net.au/bugs/1x1-tiny.png">
  <div class="content">
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
  </div>
</div>

Then to finish, we absolutely position a <div> over that square space — height: 100%; in combination with aspect-ratio: 1/1; works in this scenario. Then it’s just a matter of putting our desired <img> inside and use object-fit: cover; to scale and crop it to the space.

.container {
  background: lightgray;
  display: inline-grid;
  grid-template-columns: auto auto;
  gap: 1em;
  border: 1px solid #aaa;
  box-shadow: 0 0 1em rgb(0,0,0,0.3);
  margin: 2em;
  position: relative;
}

.intrinsic-1x1 {
  align-self: stretch;
  opacity: 0;
}

.content {
  font-size: 1.5em;
}

.overlay {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  aspect-ratio: 1/1;
}

.overlay img {
  height: 100%;
  width: 100%;
  object-fit: cover;
}
<div class="container">
  <img class="intrinsic-1x1" src="https://donald.net.au/bugs/1x1-tiny.png">
  <div class="content">
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
  </div>
  <div class="overlay">
    <img src="https://www.celebritycruises.com/blog/content/uploads/2022/01/most-beautiful-mountains-in-the-world-kirkjufell-iceland-1024x580.jpg">
  </div>
</div>

<div class="container">
  <img class="intrinsic-1x1" src="https://donald.net.au/bugs/1x1-tiny.png">
  <div class="content">
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
    <div>Content</div>
  </div>
  <div class="overlay">
    <img src="https://www.celebritycruises.com/blog/content/uploads/2022/01/most-beautiful-mountains-in-the-world-kirkjufell-iceland-1024x580.jpg">
  </div>
</div>
Brett Donald
  • 6,745
  • 4
  • 23
  • 51