Unknown User
Unknown User

Reputation: 525

Make image fit CSS Grid

I have a grid in which I position images but they doen't fill the entire space they are given.

I hope the image below illustrates the problem good enough. As we can see the top image as well as the right one don't fill the rows they are assigned to. What causes this and how can I fix it?

Code is like that:

 <section class="wrapper">
   <div class="one">
     <img class="img" src="images/lorem/ipsum.jpg" alt="">
   </div>

   <div class="two">
     <img class="img" src="images/lorem/ipsum2.jpg" alt="">
   </div>

   <div class="three">
     <img class="img" src="images/lorem/ipsum3.jpg" alt="">
   </div>
 </section>

 .wrapper {
   display: grid;
   grid-template-columns: repeat(8, 1fr);
   grid-auto-rows: minmax(150px, auto);
   grid-gap: 20px;
   height: 100vh;
 }

.one {
  grid-column: 2 / 7;
  grid-row: 1 / 3;
}

.two {
  grid-column: 2 / 5;
  grid-row: 3 / 4;
} 

.three {
  grid-column: 5 / 7;
  grid-row: 3 / 4;
}

.img {
  width: 100%;
}

enter image description here

How can I fix this?

Upvotes: 11

Views: 56693

Answers (8)

xyeres
xyeres

Reputation: 341

Browser preserving aspect ratio does appear to be the reason why this is not as straightforward as you might think.

I was able to get the image to fill a grid cell by nesting the IMG in a parent DIV and then simply applying the following to the class on the image:

I prefer this over using a background for accessibility reasons.

.image {
  aspect-ratio: 2/1;
  border-radius: var(--default-border-radius);
  object-fit: cover;
  height: 100%;
  max-width: 100%;
}

Here's a demo:

:root {
  --grid-gutter: 25px;
  --grid-max-width: 1440px;
}

.image {
  aspect-ratio: 2/1;
  object-fit: cover;
  height: 100%;
  max-width: 100%;
}

.grid {
  display: grid;
  grid-column-gap: var(--grid-gutter);
  grid-template-columns: repeat(12, minmax(0, 1fr));
  margin-left: auto;
  margin-right: auto;
  max-width: var(--grid-max-width);
  padding-bottom: 0;
  padding-left: var(--grid-gutter);
  padding-right: var(--grid-gutter);
  padding-top: 0;
  row-gap: var(--grid-gutter);
}

.large-span-4 {
  grid-column: span 4;
}

.large-span-8 {
  grid-column: span 8;
}
<aside class="four-eight grid">
  <div class="large-span-4">
    <h4 class="title">Lorem ipsum is placeholder text</h4>
    <p class="copy">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
      dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
    <div class="">
      <a href="#" class="link">Learn About It</a>
    </div>
  </div>
  <div class="large-span-8">
    <img class="image" src="https://placehold.co/600x600" />
  </div>
</aside>

Upvotes: 0

IskandarI
IskandarI

Reputation: 11

adding min-height: 0; to my img tag solved the issue for me fully. Thank you very much for your post! Best, I

Upvotes: 1

55 Cancri
55 Cancri

Reputation: 1195

I finally discovered the rules to dynamically resizing images within a css grid. They are:

  1. Every nested grid element of the parent grid must have min-height: 0 set, including the img tag itself
  2. The img tag must also define max-width: 100%
  3. The immediate grid parents of the img tags must also have min-width: 0 set for the align- and justify- properties to work correctly

Here is sample code that will work:

// parent
<div css={{
    display: "grid",
    gridTemplateRows: "max-content 1fr",
    height: "50vh",
    maxHeight: "50vh",
}}>
    <header></header>

    <div css={{
      display: "grid",
      gridTemplateRows: "3fr 2fr",
      minHeight: 0,
    }}>
        <div css={{
          display: "grid",
          minHeight: 0,
          minWidth: 0,
        }}>
            <img
                css={{
                  maxHeight: "100%",
                  minHeight: 0,
                  borderRadius: 10,
                }}
            />
        </div>

        <div css={{
          display: "grid",
          minHeight: 0,
        }}>
            {imgs.map(img => 
                <div css={{
                  display: "grid",
                  minHeight: 0,
                  minWidth: 0
                }}>
                    <img
                        css={{
                          maxHeight: "100%",
                          minHeight: 0,
                          borderRadius: 10,
                        }}
                    />
                    <p>...</p>
                </div>
            }
        </div>
    </div>
</div>

Upvotes: 0

laurent lahmy
laurent lahmy

Reputation: 1689

This worked for me using React with inline styles:

<div 
    style = {{
        gridArea: "image",
        backgroundImage: `url(${imageFromImports})`,
        backgroundSize: "contain",
        backgroundRepeat: "no-repeat",
        backgroundPosition: "center",
    }}
/>

Upvotes: 0

MosDev
MosDev

Reputation: 171

I had a similar problem to this before , the simple solution is to set the height or width to 100% for the img elements to fill their container. Then to set the object fit property to cover for better cropping. You don't even need div containers for your images. Like this:

The grid container will take care of the positioning of the cells.

img{
width: 100%;
height: 100%;
object-fit: cover;
}

Upvotes: 17

Liang Lyon
Liang Lyon

Reputation: 174

add one div to wrap your image, then set image style to .img { max-width: 100%; height: auto }

Upvotes: 9

Yan
Yan

Reputation: 353

This is normal because images are preserving their aspect ratio.

A good way to solve this common problem is to set the image as a CSS-background parameter in a div in your grid instead of an <img> tag in html, such as background: url('http://link-to-your-image/image.jpg') and use background-size: cover; on the same element.

This way, the picture will fill out all the space that is attributed to it.

Upvotes: 5

kissan
kissan

Reputation: 11

Try background-size: 100% 100% and background-size: cover or fit

Upvotes: 0

Related Questions