2

I am trying to build a card-based layout, with an image taking up the left-hand half of each card. If I use a div with a background-image, the image takes up exactly half the width, and expands to exactly the height of the content on the right-hand side of the card.

However, if I instead use an img element (with object-fit: cover), the image never crops vertically when the card is too short, but instead only horizontally when the card is too tall. How can I tell the image not to cause the card to stretch, reproducing the behaviour of the div's background image?

As an example, the third and fourth cards are what I am trying to achieve, but with an image tag for semantic reasons.

main {
  display: flex;
  flex-direction: column;
  max-width: 700px;
  margin: auto;
}

article {
  display: flex;
  flex-direction: row;
  border: 1px solid;
  margin: 1em;
}

article > img {
  object-fit: cover;
  width: 50%;
  flex-grow: 0;
  flex-shrink: 0;
}

article > div:first-child {
  background-position: center;
  background-size: cover;
  width: 50%;
  flex-grow: 0;
  flex-shrink: 0;
}

article > aside {
  padding: 1em;
}
<main>
  <article>
    <img src="https://picsum.photos/id/411/1000/900" />
    <aside>
      <h2>img taller than the text</h2>
      <p>
        Here the image extends beyond the text, which I do not want.
      </p>
    </aside>
  </article>
  <article>
    <img src="https://picsum.photos/id/411/1000/900" />
    <aside>
      <h2>img shorter than the text</h2>
      <p>
        With enough text, the image is the right height, with both the <kbd>img</kbd> tag and the background image.
      </p>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ut turpis est. Maecenas vehicula tempor purus, non laoreet turpis aliquet sit amet. Sed pellentesque augue at risus dignissim porttitor. Curabitur aliquam justo ut ante imperdiet lobortis. Aenean sit amet dui eros. Pellentesque dictum imperdiet ex in condimentum. Proin imperdiet eros a sapien egestas, quis auctor arcu laoreet. In interdum at ligula sit amet ornare. Mauris sed feugiat eros. Vestibulum in eros auctor, iaculis neque eu, tincidunt neque. Curabitur eget ligula ac tortor viverra cursus non id nunc. Morbi vestibulum ligula felis, id aliquam metus placerat at. In sed urna bibendum, volutpat ipsum et, placerat dui. 
      </p>
    </aside>
  </article>
  <article>
  <div style="background-image: url(https://picsum.photos/id/411/1000/900)">
  </div>
    <aside>
      <h2>background image</h2>
      <p>
        With very little text, the background image is cropped to take up little height, which is what I'm trying to achieve with an image tag.
      </p>
    </aside>
  </article>
  <article>
  <div style="background-image: url(https://picsum.photos/id/411/1000/900)">
  </div>
    <aside>
      <h2>background image</h2>
      <p>
        With enough text, the image is the right height, with both the <kbd>img</kbd> tag and the background image.
      </p>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ut turpis est. Maecenas vehicula tempor purus, non laoreet turpis aliquet sit amet. Sed pellentesque augue at risus dignissim porttitor. Curabitur aliquam justo ut ante imperdiet lobortis. Aenean sit amet dui eros. Pellentesque dictum imperdiet ex in condimentum. Proin imperdiet eros a sapien egestas, quis auctor arcu laoreet. In interdum at ligula sit amet ornare. Mauris sed feugiat eros. Vestibulum in eros auctor, iaculis neque eu, tincidunt neque. Curabitur eget ligula ac tortor viverra cursus non id nunc. Morbi vestibulum ligula felis, id aliquam metus placerat at. In sed urna bibendum, volutpat ipsum et, placerat dui. 
      </p>
    </aside>
  </article>
</main>
Charlie Harding
  • 653
  • 8
  • 22

2 Answers2

2

main {
  display: flex;
  flex-direction: column;
  max-width: 700px;
  margin: auto;
}

article {
  display: flex;
  flex-direction: row;
  border: 1px solid;
  margin: 1em;
}

article > img {
  object-fit: cover;
  width: 50%;
  flex-grow: 0;
  flex-shrink: 0;
}

article > div:first-child {
  background-position: center;
  background-size: cover;
  width: 50%;
  flex-grow: 0;
  flex-shrink: 0;
}

article > aside {
  padding: 1em;
}
.img-container{
  border:2px solid red;
  overflow:hidden;
  position:relative;
}
.img-container div{
position:absolute;
left:0;
top:0;
width:100%;
height:100%;
}
.img-container img{
      object-fit: cover;     
      width:100%;
      height:100%;
}
<main>
  <article>
   <div class="img-container">
   <div>
    <img src="https://picsum.photos/id/411/1000/900" />
    </div>
    </div>
    <aside>
      <h2>img taller than the text</h2>
      <p>
        Here the image extends beyond the text, which I do not want.
      </p>
    </aside>
  </article>
  <article>
  <div class="img-container">
    <img src="https://picsum.photos/id/411/1000/900" />
    </div>
    <aside>
      <h2>img shorter than the text</h2>
      <p>
        With enough text, the image is the right height, with both the <kbd>img</kbd> tag and the background image.
      </p>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ut turpis est. Maecenas vehicula tempor purus, non laoreet turpis aliquet sit amet. Sed pellentesque augue at risus dignissim porttitor. Curabitur aliquam justo ut ante imperdiet lobortis. Aenean sit amet dui eros. Pellentesque dictum imperdiet ex in condimentum. Proin imperdiet eros a sapien egestas, quis auctor arcu laoreet. In interdum at ligula sit amet ornare. Mauris sed feugiat eros. Vestibulum in eros auctor, iaculis neque eu, tincidunt neque. Curabitur eget ligula ac tortor viverra cursus non id nunc. Morbi vestibulum ligula felis, id aliquam metus placerat at. In sed urna bibendum, volutpat ipsum et, placerat dui. 
      </p>
    </aside>
  </article>
  <article>
  <div style="background-image: url(https://picsum.photos/id/411/1000/900)">
  </div>
    <aside>
      <h2>background image</h2>
      <p>
        With very little text, the background image is cropped to take up little height, which is what I'm trying to achieve with an image tag.
      </p>
    </aside>
  </article>
  <article>
  <div style="background-image: url(https://picsum.photos/id/411/1000/900)">
  </div>
    <aside>
      <h2>background image</h2>
      <p>
        With enough text, the image is the right height, with both the <kbd>img</kbd> tag and the background image.
      </p>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ut turpis est. Maecenas vehicula tempor purus, non laoreet turpis aliquet sit amet. Sed pellentesque augue at risus dignissim porttitor. Curabitur aliquam justo ut ante imperdiet lobortis. Aenean sit amet dui eros. Pellentesque dictum imperdiet ex in condimentum. Proin imperdiet eros a sapien egestas, quis auctor arcu laoreet. In interdum at ligula sit amet ornare. Mauris sed feugiat eros. Vestibulum in eros auctor, iaculis neque eu, tincidunt neque. Curabitur eget ligula ac tortor viverra cursus non id nunc. Morbi vestibulum ligula felis, id aliquam metus placerat at. In sed urna bibendum, volutpat ipsum et, placerat dui. 
      </p>
    </aside>
  </article>
</main>

Use object-fit: cover; width:100%; height:100%;. You need to specify width and height with "object-fit: cover" to achieve this.

2

You can simply make the image out of the flow using position:absolute so only the text content will define the height:

main {
  display: flex;
  flex-direction: column;
  max-width: 700px;
  margin: auto;
}

article {
  /*display: flex;
  flex-direction: row; not needed sine one element is in-flow */
  border: 1px solid;
  margin: 1em;
  position:relative;
}

article > img {
  position:absolute;
  top:0;
  left:0;
  height:100%;
  width:50%;
  object-fit: cover;
}


article > aside {
  padding: 1em;
  width:50%;
  margin-left:auto;
  box-sizing:border-box;
}
<main>
  <article>
    <img src="https://picsum.photos/id/411/1000/900" />
    <aside>
      <h2>img taller than the text</h2>
      <p>
        Here the image extends beyond the text, which I do not want.
      </p>
    </aside>
  </article>
  <article>
    <img src="https://picsum.photos/id/411/1000/900" />
    <aside>
      <h2>img shorter than the text</h2>
      <p>
        With enough text, the image is the right height, with both the <kbd>img</kbd> tag and the background image.
      </p>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ut turpis est. Maecenas vehicula tempor purus, non laoreet turpis aliquet sit amet. Sed pellentesque augue at risus dignissim porttitor. Curabitur aliquam justo ut ante imperdiet lobortis. Aenean sit amet dui eros. Pellentesque dictum imperdiet ex in condimentum. Proin imperdiet eros a sapien egestas, quis auctor arcu laoreet. In interdum at ligula sit amet ornare. Mauris sed feugiat eros. Vestibulum in eros auctor, iaculis neque eu, tincidunt neque. Curabitur eget ligula ac tortor viverra cursus non id nunc. Morbi vestibulum ligula felis, id aliquam metus placerat at. In sed urna bibendum, volutpat ipsum et, placerat dui. 
      </p>
    </aside>
  </article>

Similar question: How can you set the height of an outer div to always be equal to a particular inner div?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415