DEV Community

Cover image for What a media placeholder is and how to implement it?
Kamil
Kamil

Posted on

What a media placeholder is and how to implement it?

A media placeholder is a dummy (placeholder) for a video or image. Your media file will be loaded instead of this stub. In this article, we will consider the ways how to create a simple placeholder with a background color, and then with a blurry background image.

What is it for?

The lack of media placeholder, while reading your article from mobile devices with a slow Internet connection, can become a real problem. Users can start reading, but at a certain moment the image which will break the entire layout of the site will load, and the read text will sharply be moved down.

Example of breaking text

To analyze how your page loads with a slow internet connection, use Chrome dev tools. Network tab -> Throttling and set Slow 3G. So you can simulate a slow internet connection.

Chrome dev tools

If you use the image not in the <img> tag, you can implement the placeholder just by setting two image URLs for the CSS: background-image, At the first place, a small image which will be loaded first, then the original large image:

#image {
  background-image: url("small-image.png"), url("big-image.png");
}
Enter fullscreen mode Exit fullscreen mode

However, you should remember that, since the images are not inserted via the <img> tag, it affects the semantics. Your images will not be properly indexed by search engines.

Implementation

Let's look at the most popular placeholder implementation. To create a media placeholder, we need to create a block element with the same dimensions as the image to be uploaded later. So, we could see this element first, and then load the image without disturbing the overall layout and without moving the text. This is a kind of “spacer”, into which the picture will be loaded. To make such a wrapper is very simple:

<div class="placeholder">
  <img src="url" />
</div>
Enter fullscreen mode Exit fullscreen mode
.placeholder {
  width: 600px;
  height: 300px;
  background-color: darkseagreen;
}
Enter fullscreen mode Exit fullscreen mode

But on real websites, it is often necessary to make an image occupy all the entire available width, but retain its proportions regardless of screen resolution. So that, when viewed on devices with different resolutions, the image should occupy a certain width and, based on the width, be proportionally stretched to the desired height. An example:

example

Please note, that no matter what width the image takes, it will always maintain its aspect ratio and have the desired height. That is why all you need to know to implement this technique is the aspect ratio of your image.

Stretch blocks can be easily implemented using CSS. You need to set relative position to the wrapper block, absolute position to image and use property: padding-bottom: height/width

For example, if your photo has a width of 900px and a height of 600px, then use this ratio: 3:2 = 2/3 = 66.66%

Another examples:
4:3 = 3/4 = 75% (800px × 600px)
1:1 = 1/1 = 100% (Square image e.g. 500px × 500px)

.placeholder {
  position: relative;
  width: 100%;
  height: 0;
  padding-bottom: 66.66%;
  background-color: darkseagreen;
}

.placeholder img {
  position: absolute;
  width: 100%;
  top: 0;
  left: 0;
}
Enter fullscreen mode Exit fullscreen mode

You could also use CSS property calc: padding-bottom: calc(width/height)

As a result, we will have something like this:

result

I intentionally made a smooth animation. In real conditions, the picture is usually loaded not smoothly.

The image and its parent block are stretched and shrink to any width and at the same time, they always have the height we need.

But of course, it would be much nicer to see a preview image before the original big picture will be loaded.

Important thing. The preview image placeholder has to be very small-sized and has to has the same aspect ratio as the original big image.

The smaller the image size, the faster it will be loaded. An example of this article small image weighs 822 bytes and has size: 28px × 19px. It's enough to make a nice background preview while the user waiting for a big image. It looks like this:

Blured result

<head>
  <style>
    .placeholder {
      display: block;
      position: relative;
      width: 100%;
      height: 0;
      padding-bottom: 66.66%;
    }
    .placeholder img {
      position: absolute;
      width: 100%;
      top: 0;
      left: 0;
    }
    .placeholder .small-img {
      background-size: cover;
      filter: blur(10px);
    }
  </style>
</head>
<body>
  <picture class="placeholder">
    <img src="url of the small image" class="small-img">
    <img src="url of the big image" class="big-img">
  </picture>
</body>
Enter fullscreen mode Exit fullscreen mode

In example we blurred photo by CSS property filter: blur(10px). The value of blur property can be any unit, for example, it can be percent. The larger the value, the greater the blur. Negative numbers are not allowed. CSS property filter is badly supported by browsers, however, this task justifies using this property because users with the old browser just will see not blurred preview images.

You also need to remember that these styles for the wrapper should be loaded very first. So It’s appropriate to use a style distribution method known as critical CSS. I.e, the most important styles, that are responsible for the first rendering of the page layout, will not be loaded in a separate file. They should be inserted inside the <head> tag.

Also, small gotchas were detected during implementation. When applying the filter: blur() its blur extends beyond the boundaries of the block. It looks like this:

Blured bug

To fix it you could simply set overflow: hidden to the wrapper block. You can also come across a solution by adding negative margins. For example, margin: -10px. The value of the margin should be equal to the blur width.

Of course, the best solution would be to use back-end libraries to automatically generate small preview images with the same aspect ratio.

And don't forget about progressive images. In most cases, you can use just them.

Top comments (0)