How to make CSS grid container keep responsive square size?

Viewed 265

I want grid container to maintain square shape. So when screen is resized, it will get bigger or smaller, but it's height will be always same as it's width. I want to place 3 images inside, with top one taking up two columns, and bottom ones are square taking one column each. enter image description here

HTML:

<div class='container'>
    <div class='grid'>
        <img></img>
        <img></img>
        <img></img>
    </div>
</div>

SASS:

.container: {
  background: #fff;
  max-width: 600px;
  padding: 10px;
}

.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 10px;

  & > img:first-child {
    grid-column: 1 / span 2;
    grid-row: 1;
  }

  img {
    width: 100%;
    background-color: #000;
    object-fit: cover;
  }
}

I tried adding pseudo element to grid to maintain square ratio, only to find out that it won't work for grid. I tried giving img height: 100% but it made the too long.

I found some questions about how to keep images inside square, but non of them was about how to keep grid container square and prevent from being stretched out by children.

1 Answers

I'd do the following:

  1. Make the grid width and height responsively sized - for this use this method (.container and &::after pseudo element)
  2. Make the grid itself follow the square width and height of the container (.grid-wrapper)
  3. Use a container for the images, so that the containers resize inside the grid (1st row = 2 col wide, 2nd row = 2x1 col) (.grid-box)
  4. Use absolute positioned images in the divs, so they actually cover the divs

HTML code:

<div class='container'>
  <div class='grid-wrapper'>
    <div class='grid'>
      <div class="grid-box">
        <img src="https://picsum.photos/200/300"></img>
      </div>
      <div class="grid-box">
        <img src="https://picsum.photos/200/300"></img>
      </div>
      <div class="grid-box">
        <img src="https://picsum.photos/200/300"></img>
      </div>
    </div>
  </div>
</div>

SASS code:

$-gutter: 10px;
$-max-width: 600px;

* {
  box-sizing: border-box;
}

.container {
  position: relative;
  max-width: $-max-width;
  width: 100%;
  background: #ffff00;

  &::after {
    content: "";
    display: block;
    padding-bottom: 100%;
  }
}

.grid-wrapper {
  position: absolute;
  width: 100%;
  height: 100%;
  padding: $-gutter;
}

.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: $-gutter;
  width: 100%;
  height: 100%;

  &-box {
    position: relative;
    width: 100%;
    height: 100%;

    &:first-child {
      grid-column: 1 / span 2;
    }
  }

  img {
    position: absolute;
    width: 100%;
    height: 100%;
    background-color: #000000;
    object-fit: cover;
  }
}

Here is a Fiddle demo: https://jsfiddle.net/robertp/uLfj1swm/

And a screenshot of how this solution renders: enter image description here

Related