Search code examples
htmlcsscss-grid

How to actually arrange images in CSS GRID?


I have an svg image (with the class content__img) has a default width of 760.7 and height of 687.08, in the grid container there are 2 columns and 2 rows of `` `1fr```, this image is found in the first cell, and since the image size is bigger than the first row, the image enlarges the height of the row:

enter image description here

taking this into account

1.- If I specify that the image has a height from 100% the image does not fit the height of the first row Why is this happening? Shouldn't it be the size of the row at that moment? Because with block type elements (and the other elements in general) if they take the size of the current row, as far as I know, by default they take the width and height of the cell (it also doesn't work assigning display: block to the image)

HTML:

<body>
    <div class="content">
        <img class="content__img" src="../../assets/images/test.svg" alt="Test">
    </div>
</body>

CSS:

.content {
    width: 80%;
    height: 80%;

    background-color: beige;

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

.content__img {
    height: 100%;
}

2.- If I wrap the image in a container div (with class content__img-box), this also doesn't work, despite that the div takes the width and height of 100% of the cell, therefore, if I set the height of the image to 100%, why does the image doesn't take the 100% from the div (content__img-box)?

HTML:

<body>
    <div class="content">
        <div class="content__img-box">
            <img class="content__img" src="../../assets/images/test.svg" alt="Test">
        </div>
    </div>
</body>

CSS:

.content {
    width: 80%;
    height: 80%;

    background-color: beige;

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

.content__img {
    height: 100%;
}

This is the result I want (obviously you can give a fixed or non-dynamic size to the row and that works, but the purpose is that the image is attacked if the grid container grows):

enter image description here


Solution

  • As promised, the explaination:

    1. The grid-template-rows: 1fr 1fr; will not work as you intend to. Unfortunatly 1fr as template-row is counter-intuitive. It will not care for the parents height at all. 1fr 1fr will take the heighest row height of both rows and add the same height for the other row aswell. As such the containers height will be overwritten and as such broken. for 50% 50% to work, you need to to give the grid-contaienr a specific height!

    2. I wrapped the images inside a <div>. The whole reason to do this, is to add a the object-fit property. This will allow me to resize the image to fit inside the containing <div> without breaking its aspect-ratio and without being clipped. I added a max-height-width: 100%; to the image itself. This will down-size the image to fit inside the container (not overflow the container). But also allows the image to be smaller then the container. If I wouldnt add this but use a fixed 100%, the image aspect-ratio would be changed as the image then would fill the entire height and width no matter of the aspect ratio. Also I added display:flex, justify-content: center; align-items: center;. This will move the image into the center of the grid-card if the image does not fill out the entire grid-card.

    .content {
      height: 100vh;
      display: grid;
      grid-template-columns: 1fr 1fr;
      grid-template-rows: 50% 50%;
    }
    
    .content > div {
      display: flex;
      justify-content: center;
      align-items: center;
      object-fit: contain;
    }
    
    .content > div > img {
      max-height: 100%;
      max-width: 100%;
    }
    
    /*for demonstration purpose only */
    body {
      margin: 0;
    }
    .content > div {
      border: 2px solid red;
    }
    <div class="content">
      <div>
        <img src="https://via.placeholder.com/1024x720.svg">
      </div>
      <div>
        <img src="https://via.placeholder.com/800.svg">
      </div>
      <div>
        <img src="https://via.placeholder.com/1920x1080.svg">
      </div>
      <div>
        <img src="https://via.placeholder.com/150x300.svg">
      </div>
    </div>