Roman Kovalchik

Dealing with images while writing a WordPress project

May 29, 2022
  1. Introduction
  2. Compression
  3. Lazy loading
  4. PHP function


Images optimization is the most important part of the loading speed of any website. In this article, we will look at the problems that a developer may encounter creating a WordPress theme and find optimal solutions.

Writing a WordPress theme, we need to achieve the following:

  1. Image compression (if necessary)
  2. Lazy loading technique
  3. Absence of layout shift effect during lazy loading
  4. Making images responsive to screens of all sizes
  5. Adaptation of loading an image of the appropriate size for different screens

It’s also worth considering that the administrator of the site you’re developing the theme for may upload images to the media library that are much larger than what’s needed to display on the web page. Thus significantly slowing down the page loading speed.

The built-in Gutenberg editor in WordPress achieves most of these things by default, so the tips in this article are about working with custom page templates where the developer is in control of everything by himself.

Let’s start with something more obvious and simple.


In the case of a WordPress project, as with any other CMS, images can be divided into two types – static and dynamic. Static images are placed inside the theme’s file system, so the site administrator has no access to interact with them.

Compression of static images should be done by the developer. To do this, I use the imagemin npm package, which allows to optimize all available images to various levels of quality. Using this package, you just need to perform one command inside the editor’s terminal and a few seconds of time.

You can read more about automating the WordPress project development process in my article WP-Starter. WordPress theme starter template.

Dynamic images that are uploaded to the media library by the administrator can be pre-optimized through online services or using installed plugins.

Lazy loading

To significantly speed up the loading of the site page, the loading of images is delayed until the moment when they are in the visibility zone of the user’s browser window. That is why loading is called “lazy”.

To achieve this goal, I use the vanilla-lazyload library. In my case, the integration of this library is implemented in two lines of JS code:

import LazyLoad from 'vanilla-lazyload'

new LazyLoad()

After that, the image markup will look like this:

<img data-src="image.jpeg" class="lazy">

You can add the following styles to make your images appear smoothly:

/* SCSS */
img[data-src] {
  transition: opacity 0.2s;
  &:not(.loaded) {
    opacity: 0;

Layout shift

Making an image responsive to screens of all sizes is quite simple. But since the image block does not initially have a fixed height using lazy loading, all the content below will move down as the image loads. This looks annoying and also leads to bugs – for example, when using the smooth scrolling effect on the page, since the page height will constantly change as images load.

So how do you apply a lazy loading effect to an image, avoiding vertical shifting of the content and keeping the image responsive for all screen sizes?

Here is my solution:

<div class="fit" style="padding-bottom: 69.3%">
 <img data-src="image.jpeg" class="lazy">
/* SCSS */
.fit {
  position: relative;

  & > img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;

The value of the padding-bottom property, which in this case is 69.3%, is the percentage of the image’s height relative to its width. Calculated as follows:

Height (px) / Width (px) * 100

For example, you have an image container that is 500px wide and 700px high. In this case, the value of padding-bottom will be 500 / 700 * 100 = 71.4%. Now we have a fully responsive block, it remains to place an image in it.

The magic happens with the object-fit CSS property. Now we can either stretch the image over the entire block using the cover value, or fit the entire image inside the block using the contain value. You can also define the alignment of an image with respect to its parent box using the object-position property.

Now any image that will be placed in this container will display correctly, as intended by design.

PHP function

I use this function in 100% cases dealing with images when creating a WordPress project. It is implemented as follows:


 * Get responsive image html by image id
 * @param   int       $image_id
 * @param   string    $image_size default wp image size (thumbnail, medium, medium_large, large, full, or any custom created)
 * @param   string    $max_width maximum possible image width
 * @param   bool      $lazy should image be lazy loaded
 * @param   bool      $lazy_in_slick should image be lazy loaded inside slick carousel
 * @param   string    $classes additional classes for the image
 * @return  string  echo image html with srcset and alt attribute
 * author: https://www.kovalchik.com.ua

function get_img($image_id, $image_size = 'full', $max_width = '100vw', $lazy = true, $lazy_in_slick = false, $classes = '') {

  $default_image_src = wp_get_attachment_image_url($image_id, $image_size);
  $image_srcset = wp_get_attachment_image_srcset($image_id, $image_size);
  // get image description for the alt tag from media library; set image name without extension if description is missing 
  $alt = get_post_meta($image_id , '_wp_attachment_image_alt', true);
  if (!$alt) {
    $path_parts = pathinfo($default_image_src);
    $alt = $path_parts['filename'];

  if ($lazy_in_slick == true)
    echo "<img alt='{$alt}' class='{$classes}' data-lazy='{$default_image_src}' srcset='{$image_srcset}' sizes='(max-width: {$max_width}) 100vw, {$max_width}'>";

  else if ($lazy == true)
    echo "<img alt='{$alt}' class='lazy {$classes}' data-src='{$default_image_src}' data-srcset='{$image_srcset}' data-sizes='(max-width: {$max_width}) 100vw, {$max_width}'>";

    echo "<img alt='{$alt}' class='{$classes}' src='{$default_image_src}' srcset='{$image_srcset}' sizes='(max-width: {$max_width}) 100vw, {$max_width}'>";

I usually use the Slick library to create sliders. This library already implements lazy loading of images, so the $lazy_in_slick argument has been added to the function, which determines whether the current image will be located inside the slider with the appropriate markup.

Attribute srcset

This attribute of the <img> tag allows the browser to determine which image to load on the page based on the screen width. That is, on a mobile device, we do not need to load a large image that is intended for a desktop.

But for this we need to have the same image with different sizes. And since we are dealing with a WordPress project, after uploading the images to the media library, we already have them. As well as we have the wp_get_attachment_image_srcset function, which is responsible for generating the necessary markup for this attribute.

The final markup and php for images looks like this:

<div style="width: 95px">
  <div class="fit" style="padding-bottom: 37.8%">
    <?php get_img($image_id, 'thumb', '95px') ?>

In this case the second argument to the get_img function is the image size called thumb (150×150), since the maximum width of the parent block for an image is 95px.

With the help of this argument, we determine from what size of the image the content of the srcset attribute will be formed in a downward order. In this case, it will be the only path to a single image for all screens, because the thumb size is the smallest of all the default WordPress image sizes.

To better understand how this function works, I advise you to test it yourself.

That’s all. Share your experience dealing with images in the comments.

And be kind.

May 29, 2022
Like 2

Leave a Reply

Your email address will not be published.

learn-english-1024x570 Education
Sep 08, 2021

How to learn a foreign language. Practical guide

I have studied English since the first grade of high school, attending school Olympiads. After high school, I studied English at the institute...

gym Sport
Nov 02, 2021

Power training of Ectomorph. Major mistakes

Almost all my life is related with various sports. And in most of them I managed to achieve a certain result thanks to my perseverance...

helpersScss Development
Sep 19, 2021

Helpers.scss. Library for comfortable CSS workflow

Helpers.scss library adheres to the basic principles of the well-known TailwindCSS library. But on the author's opinion...