Justified Image Grid only with CSS & HTML

Thanks to new CSS features, we can finally create a responsive and justified image grid using only CSS and HTML.


Content of this Article

  1. Preview
  2. HTML Structure
  3. CSS Part
  4. Settings
  5. PRO Tip

Preview

First, let’s take a look at what we are building in this article. We build a grid of images, each with any aspect ratio. The images are never cut off or distorted, but always arranged in such a way that they result in a perfect grid. The grid always adapts perfectly to the device and its available width.

  • image 1
  • image 2
  • image 3
  • image 4
  • image 5
  • image 6
  • image 7

HTML Structure

Let’s see the HTML structure first. Semantically we want to show a list of images, so we use a <ul> element and we set the class justified-image-grid. The <li> elements are the items each with an image:

<ul class="justified-image-grid">
  <li>
    <img src="https://loremflickr.com/640/480/butterfly?random=1" alt="image 1" />
  </li>
  <li>
    <img src="https://loremflickr.com/480/640/butterfly?random=2" alt="image 2" />
  </li>
  <li>
    <img src="https://loremflickr.com/800/600/butterfly?random=3" alt="image 3" />
  </li>
  <li>
    <img src="https://loremflickr.com/800/450/butterfly?random=4" alt="image 4" />
  </li>
  <li>
    <img src="https://loremflickr.com/480/640/butterfly?random=5" alt="image 5" />
  </li>
  <li>
    <img src="https://loremflickr.com/480/640/butterfly?random=6" alt="image 6" />
  </li>
  <li>
    <img src="https://loremflickr.com/640/480/butterfly?random=7" alt="image 7" />
  </li>
  <!-- If you need something fancier, check out https://gridzy.gallery/ -->
</ul>

This is pretty simple so far, but before we can go to the CSS part, we need some inline styles.

We have to manually specify the width and height of each item as a custom property so that the CSS part can calculate the grid correctly.

The easiest way is to just use the width and height of the original image size:

<ul class="justified-image-grid">
  <li style="--width: 640; --height: 480; ">
    <img src="https://loremflickr.com/640/480/butterfly?random=1" alt="image 1" />
  </li>
  <li style="--width: 480; --height: 640; ">
    <img src="https://loremflickr.com/480/640/butterfly?random=2" alt="image 2" />
  </li>
  <li style="--width: 800; --height: 600; ">
    <img src="https://loremflickr.com/800/600/butterfly?random=3" alt="image 3" />
  </li>
  <li style="--width: 800; --height: 450; ">
    <img src="https://loremflickr.com/800/450/butterfly?random=4" alt="image 4" />
  </li>
  <li style="--width: 480; --height: 640; ">
    <img src="https://loremflickr.com/480/640/butterfly?random=5" alt="image 5" />
  </li>
  <li style="--width: 480; --height: 640; ">
    <img src="https://loremflickr.com/480/640/butterfly?random=6" alt="image 6" />
  </li>
  <li style="--width: 640; --height: 480; ">
    <img src="https://loremflickr.com/640/480/butterfly?random=7" alt="image 7" />
  </li>
  <!-- If you need something fancier, check out https://gridzy.gallery/ -->
</ul>

As you can see, we set a style attribute for each <li> element. There we define the custom properties --width and --height. The value of the custom property is only a number without any unit so we do not use 640px but just 640 for example. The values for width and height correspond to the original width and height of the image of the respective item.

To be precise, the values are only used to calculate the aspect ratio of the item, so instead of --width: 640; --height: 480; also --width: 4; --height: 3; could be used.

CSS Part

If we have set up the whole HTML part, we can now go to the CSS part, which is pretty simple. You can just copy and paste the following snippet:

<style>

/* Settings start */
.justified-image-grid {
  --space: 4px;
  --min-height: 190px;
  --last-row-background: rgb(3, 124, 168);
}
/* Settings end */

.justified-image-grid {
  display: flex;
  flex-wrap: wrap;
  grid-gap: var(--space);
  list-style: none;
  margin: 0 !important; /* We use !important to avoid gaps in some environments. */
  padding: 0 !important; /* We use !important to avoid gaps in some environments. */
}

.justified-image-grid > * {
  flex-grow: calc(var(--width) * (100000 / var(--height)));
  flex-basis: calc(var(--min-height) * (var(--width) / var(--height)));
  aspect-ratio: var(--width) / var(--height);
  position: relative;
  overflow: hidden;
  margin: 0 !important; /* We use !important to avoid gaps in some environments. */
  padding: 0 !important; /* We use !important to avoid gaps in some environments. */
}

.justified-image-grid > * > img {
  position: absolute;
  width: 100%;
  height: 100%;
}

.justified-image-grid::after {
  content: " ";
  flex-grow: 1000000000;
  background: var(--last-row-background);
}

/* If you need something fancier, check out https://gridzy.gallery/ */

</style>

When you’ve got everything set up, it should look like the preview we saw earlier. Here we have it again:

  • image 1
  • image 2
  • image 3
  • image 4
  • image 5
  • image 6
  • image 7

Does this article help you?

If you want to help me too, just send me the amount this article is worth to you. It helps me move on and understand what people want to read the most 😉


Settings

As you may have seen there are some settings in the CSS part. Let’s take a look:

/* Settings start */
.justified-image-grid {
  --space: 4px;
  --min-height: 190px;
  --last-row-background: rgb(3, 124, 168);
}
/* Settings end */

Space

--space defines the space between the items. You can simply change the value in the CSS part or you can define it in the HTML part like this:

<ul class="justified-image-grid" style="--space: 1em; ">
...

As you can see in the example, you can use em or any other unit instead of px. The easiest way, however, is px of course.

Minimum Height

--min-height defines the minimum height of an image line. You can change it in the CSS part or in the HTML part like this:

<ul class="justified-image-grid" style="--min-height: 5em; ">
...

You can also use any unit here.

Last Row Background

--last-row-background defines the background of the empty space in the last row. This can be a CSS color or any other CSS background. Change it in the CSS part or in the HTML part, whatever you want.

Use --last-row-background: none; to let the space empty without any background.

You can also use repeating-linear-gradient() to make stripes for example:

<ul class="justified-image-grid" style="--last-row-background: repeating-linear-gradient(-45deg, #eee, #eee 10px, #ddd 10px, #ddd 20px); ">
...

Okay, let’s set all settings at once in the HTML:

<ul class="justified-image-grid" style="
  --space: 1em;
  --min-height: 5em;
  --last-row-background: repeating-linear-gradient(
    -45deg,
    #eee,
    #eee 10px,
    #ddd 10px,
    #ddd 20px
  );
">
  <li style="--width: 640; --height: 480; ">
    <img src="https://loremflickr.com/640/480/butterfly?random=1" alt="image 1" />
  </li>
  <li style="--width: 480; --height: 640; ">
    <img src="https://loremflickr.com/480/640/butterfly?random=2" alt="image 2" />
  </li>
  <li style="--width: 800; --height: 600; ">
    <img src="https://loremflickr.com/800/600/butterfly?random=3" alt="image 3" />
  </li>
  <li style="--width: 800; --height: 450; ">
    <img src="https://loremflickr.com/800/450/butterfly?random=4" alt="image 4" />
  </li>
  <li style="--width: 480; --height: 640; ">
    <img src="https://loremflickr.com/480/640/butterfly?random=5" alt="image 5" />
  </li>
  <li style="--width: 480; --height: 640; ">
    <img src="https://loremflickr.com/480/640/butterfly?random=6" alt="image 6" />
  </li>
  <li style="--width: 640; --height: 480; ">
    <img src="https://loremflickr.com/640/480/butterfly?random=7" alt="image 7" />
  </li>
  <!-- If you need something fancier, check out https://gridzy.gallery/ -->
</ul>

And now let’s see the result:

  • image 1
  • image 2
  • image 3
  • image 4
  • image 5
  • image 6
  • image 7

That’s awesome, isn’t it?

PRO Tip

If you need something fancier, check out Gridzy.Gallery.


Does this article help you?

If you want to help me too, just send me the amount this article is worth to you. It helps me move on and understand what people want to read the most 😉

Be the first to leave a reply …

or

You can post as a guest if you like. But please consider, that I always review such comments before I switch them public, to prevent spam. If you want to see your comment public immediately, just sign up and in. It's just a click away and it's really simple. You don't even need a password. 😉