How to create a Grid of squares

How to create a Grid of squares

The problem

You want to display items side by side in a grid. You set the number of columns, and you want each item's height to match its width to form a square. How do you do this?

I faced this problem at work. I needed to create a gallery like on iPhone, WhatsApp, or Telegram, where you see a grid of images and can click on them to view in full screen.

Achieve equal width

To achieve the items having equal width, we can use display Grid.

<div className="grid grid-cols-4 gap-1">
  {images &&
    images.map((image) => (
      <img key={image.id} src={image.url} alt="image" className="w-full" />
    ))}
</div>

This will give us a grid of 4 columns with a gap of 4px. Each column will take equal width. The images will take the full width of the column and their height will adjust to maintain the aspect ratio.

The issue here is that we want the images to take equal height. Once that's done, we could use object-fit: cover; to ensure the images cover the entire space and their aspect ratio is maintained.

Achieve equal height

To make height the same value as the width, we can use padding-top: 100%; to achieve this. When you use padding with percentage, it's calculated based on the width of the element.

<div className="grid grid-cols-4 gap-1">
  {images &&
    images.map((image) => (
      <div
        // padding top 100% to ensure square based off the width
        className="relative w-full pt-[100%]"
        key={image.id}
      >
        <img
          src={image.url}
          alt=""
          className="absolute left-0 top-0 h-full w-full object-cover"
        />
      </div>
    ))}
</div>

As you can see, we now have a wrapper around the image.

Let's try to understand how things work here in chronological order:

  1. div is the wrapper. It takes full width and its height is the same as the width.

  2. div has padding-top: 100%;. This means it will naturally push down the image inside of it to fill the space.

  3. Therefore, the image can not be inside the normal flow of the document.

  4. div is given relative positioning.

  5. img is given absolute positioning and can be placed anywhere.

  6. Because the parent of img has relative positioning, the img will be positioned relative to its closest ancestor that has relative or absolute positioning.

  7. img is given left: 0; top: 0;. This means the top left corner of the image will be at the top left corner of the div.

  8. img is given h-full w-full. This means the image will take the full height and width of the div.

  9. img is given object-cover. This means the image will cover the entire space of the div and its aspect ratio is maintained.

And that's how you achieve a grid of squares.