This is an issue that affects WordPress websites that have lots of uploaded images, such as news websites, photographers, food blogs, etc. So if you find yourself uploading lots of images into your WordPress media library every month – keep reading.
1. The Default WordPress Image Sizes from Media Settings
Let’s start with a bit of history.
When WordPress was first introduced, it came with a very cool and appreciated feature: it would automatically create images of three different sizes for each image that you upload. WordPress made it easy to upload large photos without worrying about their size, because you could easily insert smaller, cropped versions into your content.
You simply go to Dashboard > Settings > Media and choose the values for these 3 core sizes: Thumbnail, Medium, Large. Simple enough.
The average user didn’t have to worry too much about uploading that DSC_3795.jpg file straight from their camera, probably a 4000x2666px ~8MB file. No matter what size the uploaded original had, you simply choose the Thumbnail or Medium size and import it into your content.
When the time came to switch to a different WordPress theme, sometimes users had to change some of their image sizes, so as to better fit the new layout and design. Maybe the content is now 100px wider, so those Medium 600×400 images should now be 700×450.
A new problem popped up: changing the size in Settings > Media doesn’t do anything about images that already exist in the Media Library. These old images were created using old sizes, so older posts don’t look as good.
To help in that transition developers started recommending plugins like Regenerate Thumbnails, a free WordPress plugin (active on over 1 million websites) that creates image files using current Media settings for all existing images.
Now with a bit of adjustments and edits users could continue working on their websites without worrying about badly-sized images. Problem solved.
2. And then add_image_size() was introduced in WP 2.9
WordPress version 2.9 was released on December 18, 2009.
One of the new functions that proved to be crucial to the huge success and adoption of WordPress was the add_image_size() function.
This function allowed theme developers to define even more custom image sizes, but this time users did not have easy access to altering these custom sizes.
So if a theme developer wanted to create a custom block in their theme that would display the latest post with a 100×100 thumbnail next to it – they would simply add a line of code into their theme like this one:
<?php
add_image_size( 'thumb-loop-small', 100, 100, true );
?>
Developers could specify this size in their custom section and they were pretty sure that everything would work as expected. Users couldn’t just easily change the size to 300×50, as they had to get into the theme’s template files, as in edit actual code.
This signaled the start of a race for the most original placement of content on a single page. Theme developers went crazy creating blocks and widgets with custom content everywhere.
Allow me to illustrate with one of my earliest magazine WordPress themes (Telegraph) released in January of 2011, back when 960px was the norm. I drew up some stuff in Photoshop, looked for ways to organize content and images, and I came up with a homepage that looked like this:
<?php
add_image_size( 'widget-photo-category', 300, 200, true );
add_image_size( 'homepage-slider', 280, 160, true );
add_image_size( 'quick-posts', 145, 100, true );
add_image_size( 'loop-main', 100, 80, true );
?>
In this theme I had defined 4 custom image sizes. Call me a bad designer or planner, but hey, we all make mistakes.
3. The Problem with Image Sizes in WordPress
Now let’s look at the issues that can be caused by all these image sizes in WordPress. We will continue with the simple example of Telegraph theme from the above, which uses 4 custom image sizes.
When a user of that theme would upload a 1600×1200 image into WordPress, here are the images that WordPress will create and keep on the server forever:
- /uploads/2018/08/beautiful-photo.jpg — the original photo is kept
- /uploads/2018/08/beautiful-photo-1024×1024.jpg — the default large size
- /uploads/2018/08/beautiful-photo-300×300.jpg — the default medium size
- /uploads/2018/08/beautiful-photo-150×150.jpg — the default thumbnail size
- /uploads/2018/08/beautiful-photo-300×200.jpg — the custom ‘widget-photo’category’ size
- /uploads/2018/08/beautiful-photo-280×160.jpg — the custom ‘homepage-slider’ size
- /uploads/2018/08/beautiful-photo-145×100.jpg — the custom ‘quick-posts’ size
- /uploads/2018/08/beautiful-photo-100×80.jpg — the custom ‘loop-main’ size
A total of 8 files will be created and kept on your web hosting server just because of a single uploaded image. Now imagine if you have 5 photos in each post, that’s 40 files per post.
If you are a food blogger or a photographer, it is not uncommon to have 20-30 photos in a single post. Multiply that by 8 (in this particular case) and you get hundreds of file on the server just because of a single post or page.
Here’s an example of a very simple photographer blog and the amount of files generated on the server:
There are 50 photos in this standard post. Each uploaded photo takes up 9 files on the server. That’s 450 files on the server from a single post that has zero incoming traffic.
Another customer of mine is using a VERY popular magazine WordPress theme and currently has 2,191 uploaded image files on his WordPress blog.
His theme and plugins have a combined number of 19 custom image sizes. Including the original and default media sizes, there are a total of 23 files for each of his uploaded image. 2,191 x 23 = 50,439 files.
A small 55KB image actually takes up 650KB because of all the alternatives sizes created for no real purpose.
Just look at this “beauty” and tell me if this looks sustainable:
Why do I care? I have unlimited hosting disk space!
Not so fast.
True, many web hosting providers advertise their packages as unlimited disk space. But we all understand that unlimited is not really unlimited. There are other limitations that they will impose (and for good reason).
For example HostGator’s hosting packages (incidentally I strongly recommend against using HostGator, here’s why):
Even though the actual disk space is “unmetered”, you lose some features once your number of inodes reaches a certain number.
Think of inodes as unique files that are in your hosting account. Each file that exists on the server is one inode. Each email that you receive and let it stay on the server is equal to 1 inode.
Using the photographer’s website from the example above, that single post adds 450+ inodes towards the account’s total usage.
And what happens once we reach our inode limit? Nothing horrible, but something bad nonetheless. Here’s the notice that you get if you’re hosted with HostGator:
Files 156360 / 100000
Size 15352.70 / 20000 MB
Error: If Backups ran now, your account would NOT be backed up.
In translation: if you exceed your inodes limit (in this case: 100,000) then automatic backups are not run. HostGator absolves themselves of risks and responsibilities, so you are on your own.
Here’s another example of SiteGround, a hosting that I really like (this very website is hosted with them).
Even though their hosting plans comparison doesn’t mention anything about an inodes limit, as a customer we find that limit in cPanel:
In this case the limit is 450,000 which sounds a lot. But once you think of the 450 files per post example, that becomes less impressive.
Now that we’ve determined and understood the issue and the risks that come with it, let’s work towards a solution.
4. How to Identify Custom Images Sizes in Your Theme?
There are two good ways to identify which custom sizes are currently defined on your WordPress website.
4.1. By checking your /wp-content/uploads/ folder
The surest way is to upload a large ~2000x2000px test image and then check the corresponding upload folder for all alternative files that were created.
You can either log in using a FTP client (like FileZilla) or by using the File Manager module from cPanel.
Go to /wp-content/uploads/CURRENT YEAR/CURRENT MONTH/ and find the file that you have just uploaded. Here’s what it would look like in FileZilla:
As you can see in this case, the original file is the largest (naturally), and then there are 6 extra files. So we deduct the 3 built-in media sizes (thumbnail, media and large) and we’re left with 3 extra custom sizes, which is not ideal.
4.2. By checking your theme’s files
Another way would be to look out for the add_image_size function in your theme’s files. Most WordPress themes define custom sizes somewhere in the functions.php file.
So go to Appearance > Editor > functions.php and do a search in your browser’s tab (CTRL+F) for the function add_image_size. The complete code looks similar to the one at the beginning of this post.
This method will not work if you don’t have permissions to edit theme files, so the page Appearance > Editor will not even be available to you. This method will also not work if your theme uses a more sophisticated file structure and defines custom images sizes elsewhere.
5. How do I reduce the number of generated files?
There are a few good ways to reduce the number of custom image files that are generated by WordPress.
Whichever method you choose, it is best if you know your website well. You should be aware of your content blocks, sections, custom templates, etc.
5.1. Disable the default WordPress Media sizes
As stated earlier, WordPress will usually create a minimum of 4 files for each uploaded media file: the original, large, medium and thumbnail versions.
Many websites don’t even use the large/medium/thumbnail sizes, as they are usually used for inserting the images into the page/post content. Most themes define their own custom sizes.
Disabling the default Media sizes is simple as pie.
Go to Dashboard > Settings > Media and set the width and height to 0 (zero) for the sizes that you want to disable. Clicking on “Save Changes” will not do anything to your existing files, it will only prevent WordPress from generating these sizes on future media file uploads.
Is this method for me?
It depends. Let’s look at my NewsToday Magazine WordPress theme as an example.
The theme defines one custom size:
<?php
add_image_size( 'newstoday-thumb-featured', 740, 480, true );
?>
Images of this size are displayed in two places: on the homepage for the first featured post, but also on inner post pages too (inside posts). So these images are not used for a single, temporary purpose (for a short-time spot on the homepage), rather they are used throughout the website at all times.
This is a better way of using and implementing custom image sizes. Many users of my theme won’t even need to insert other images into the post, unless they have images with a different ratio (portrait-sized).
5.2. Disable custom image sizes defined in the theme
If you have determined that your current WordPress theme defines too many custom sizes, especially ones that you don’t even use, then consider disabling them.
The best way would be to use a child theme and make a couple of calls to the remove_image_size() function.
<?php
add_action('init', 'ilovewp_remove_image_sizes');
function ilovewp_remove_image_sizes() {
remove_image_size('custom-image-size-name');
}
?>
Why use a child theme?
If you edit your theme’s template files directly, then you will lose your changes on your next theme update, unless you don’t intend to update your theme.
5.3. Switch to a different theme
If you’ve been considering switching to a different theme and your current theme uses too many custom sizes, then maybe now is a good time to make the switch. You can find some interesting WordPress themes here.
6. I have disabled custom sizes and nothing happened
I mentioned this before: simply changing, adding or disabling custom image sizes in WordPress doesn’t do anything about your existing images. You now have to install a WordPress plugin to take some actions in regards to your existing images.
I recommend using the Force Regenerate Thumbnails, which works a little differently from the Regenerate Thumbnails plugin.
It doesn’t just generate new images for your new sizes, it also deletes all your image versions that are no longer in use. So it deletes all versions except the originals and then generates new thumbnails that are only currently active.
I was tasked with fixing some issues on a photography blog that was having performance issues. Upon inspection I have discovered 11 custom images sizes in a theme that wasn’t even using them.
After some optimization, the plugin had to delete 15 files and then regenerate only 4 instead for each media file.
Two hours later there were 90,000 less files and about 10 GB worth of disk space. Even if your web host doesn’t limit your number of inodes or the disk space, consider that your weekly/monthly backups will be much lighter and easier to manage.
7. An Open Call to Theme Developers
If you are a WordPress theme developer or just doing some custom work, please be careful with the add_image_size() function.
7.1. Plan better and use less custom image sizes
I know it is very easy to just slap a couple of them for each little thing that you thought of, but maybe there is a way to re-use an already defined size? Usually there is.
When you are in the planning phase consider using images with the same ratio. So if you have a block that displays square 400×400 images, then consider making your other blocks use square images too. Then you could load the larger images and then scale them down via CSS.
Scaling down a 400×400 image to 250×250 is easy and simple, while scaling down a 400×400 to 300×150 is not.
7.2. Include information about your custom sizes in the documentation
If you define and use custom image sizes in your theme then it is best to state that on the documentation page for the theme (or in readme.txt). Do this especially if you define custom sizes in a different file other than functions.php.
7.3. Add your custom image sizes to the Media Import selector
And finally, if you decided that custom image sizes are required and WordPress creates them, then you should add them to the Add Media size dropdown selector.
You can add something like this to your functions.php:
<?php
add_filter( 'image_size_names_choose', 'ilovewp_custom_sizes' );
function ilovewp_custom_sizes( $sizes ) {
return array_merge( $sizes, array(
'ilovewp-thumb-featured' => __( 'Custom Size: Slideshow Size', 'textdomain' )
) );
}
?>
Now your authors and users should be able to use your custom image sizes anywhere they please, not just where you hard-coded it into.
In Conclusion
I understand that some readers might consider this topic a little trivial and not worth the 2,200+ words written here.
But please stop for a minute and consider the potential footprint of badly implementing custom image sizes. It is estimated that there are over 70 million WordPress websites.
When you consider the potential resource gains from properly planning and using image sizes in WordPress, we might be able to shave off tens of billions of files that just sit there, idly, using up energy.
No matter what your reasoning is, be it to reduce your hosting bill or to reduce your environmental footprint, there’s no reason to keep creating unnecessary data.
Peace!
18 Comments
God, I’ve been waiting for this post for more than 10 years! Can’t believe this issue is not being discussed more often and not dealt with more easily.
As a developer, the amount of work required to maintain a clean uploads folder for my clients is quite substantial, using all of the above plugins. Plus you really need to know what you are doing, especially when you switch themes.
For a less seasoned dev guy this is probably even harder, and for a client it is close to impossible.
I would really love seeing WP dealing better with image sizes, but let’s get over Guttendrama first 🙂
Thanks for a great post!
Yes! And something else in the same problem – when the number of inodes in a directory folder rises above a limit (number depending on filesystem configuration) the directory access uses more time and memory. This small problem is most visible in DMS solutions where document storage is built to distribute the inodes evenly over a number of folders and never over the limit from the old Unix filesystem. For WP it is only the images that gets into the trouble zone 😀
How do I discover the ‘custom-image-size-name’ so as to disable them in my child theme function.php? I searched through all of my plug-in files for ‘add_image_size’ but found nothing. (I see in the Uploads folder 6 additional image sizes in addition to the thumbnail, medium, and full sizes for every image that has been uploaded)
Nevermind. The theme had the add_image_size() function… Good article, I’ve been wanting to remove the extra files in the uploads folder for quite some time.
Thanks for this! Completely agree on the sentiment. This is a very brute-force way to deal with images. Hopefully eventually things will change towards efficiency.
It’s not developers fault to have so many image sizes, but designers, so change “An Open Call to Theme Developers”, to “An Open Call to Theme Designers” 🙂
Where was this article three years ago?! Thank you for posting this! We have a 5-year-old travel website with hundreds of photos. A year ago, we converted to a fabulous new theme, but it automatically creates 12 copies which are used throughout our image-heavy site. I’ve finally figured out how to use GIMP to compress and resize our images to reduce server usage. The Force Regenerate Thumbnails was invaluable when we converted to our new theme. Unfortunately, we’re now having problems with the plugin. It appears it’s not supported anymore? Recently when we “force regenerate thumbnails,” it deletes images which are IN USE in blog posts! This leads to broken links and no images on that post. Do you know anything about the status of this plugin, by chance? We’re really sad to have to delete it, but we have no choice if it continues to wreak havoc with our site. 🙁
Last week I had the same problem with the WP’s image sizes. It’s complete nonsense and a lot of redundancy and unnecessary files.
Anyway, after going through a bunch of StackOverflow I ran into a really useful plugin, although it can be coded, without using a plugin. The plugin is Fly Dynamic Image Resizer.
It basically fools WP system for creating images and generates only necessary image sizes, when they are needed. Once the image is created for the first visitor, it will be served from the server since it’s already in the media library. For me, it’s a life saver since I can easily create different image sizes for specific images, and skip the sizes I don’t need.
Plus, it works automatically when you add a new image size in code. No need to regenerate thumbnails.
I’m not sure why this would be a good solution.
Once a bot visits your page, it would generate the images and then have them there on the server, forever.
You simply postpone the creation of files from the moment of upload to a few hours/days in the future.
This doesn’t resolve the problem of having all these generated images on the server.
Or did I misunderstand something?
What about the srcset part of the “ tag? I guess this plugin does not handle it, so what about the responsive behaviour of the images?
This article precisely puts its finger on every pain point I have with images in WordPress.
Generating image thumbnails only when they are needed is the best solution. I don’t know why this isn’t a core feature (I can’t even find a feature request for it).
I also work in Drupal, which handles this brilliantly.
1. It has a UI in core for creating your own image styles (like thumbnails, but you can do other cool things including recoloring, rotating, watermarking, changing format, and optimizing). You can then choose which image style to use when placing an image.
2. Image styles are only generated from the original image when that style is needed. They are then stored for future use in a folder specific to that image style.
3. If you change the definition of an image style, a new image based on the new image style will be generated – but not until next time that image is requested.
4. You can flush your image styles to remove unwanted images – those that are still being used in the site will simply be regenerated as needed.
5. For responsive images, you can create your own image sets with different image styles for each breakpoint. Then, when uploading an image, you can choose the image set that you want for that particular use.
Thanks for this post. It’s helped me understand this issue a lot more.
I’ve known there’s a growing problem with images on my site for a while now.
And this post has given me the information to at least understand the history of how WordPress treats images and how to keep them to a minimum. The lack of good information on this is so frustrating.
I stopped using a plugin that created some images. But when I decided to stop using the plugin. And removed it, I expected the size of my backup to reduce. Because I expected the pluging to clean up after itself. More fool me. Checked my uploads folder and there the images all were. Ugh!!
I didn’t know what do do about them. Can you tell me if I can I manually delete the images?
I know the ones the plugin put there. Because of the date of the folders partly and they have weird names assigned to them. The images I upload have sensible names.
Great article. I totally agree this needs to be discussed more.
The goal of having a lower usage of add_image_size is noble … and yet we are entering an era where we need more and more image croppings available. The built in compatibility with srcset and responsive images is really working great in WP now with a high level of browser support too, but if you want to take full advantage of it, you need to provide 3, 4, maybe 5 image files per hard-cropped aspect ratio.
The current project I’m working on has 5 non-hard-crop sizes, 3 square cropped sizes, 4 wide banner cropped sizes, 5 landscape (3:2 aspect ratio) sizes, and a handful more for specific scenarios. About 20 total sizes and every single one of these is carefully planned and definitely needed.
I heartily second @David P’s comments about how Drupal does things. Just so everyone understands – the way that system works is the original image is the ONLY one on the server to start. It’s when the first user requests the first page with a certain cropping that the cropped version is generated on the fly. This leads to a very lovely situation where – for example – if you upload a file just for use in a banner location – the banner shaped croppings will be generated – none of the other sizes will. If you upload another file for an avatar that gets cropped square only the sizes actually implemented on the front end ever get generated. So you end up with what I imagine as a sort of spreadsheet where the sizes are the column headers at the top and each original image is a row – and there are smattering of green dots just where the images are needed. The same spreadsheet in WordPress has a green dot in every single cell of the entire spreadsheet – a sea of green.
I wonder if we will ever see something like that in the WordPress core? The GUI for the WordPress media managment is so awesome and great for non-technical users compared to Drupal and other CMS systems I’ve used. If we could just figure some way to get the backend to avoid producing a full set of images for each original – most of which probably never see the light of day – that would be so fantastic.
Thanks for this helpful post – we had the same problem, and managed to overload our server host without realising. I considered trying the plugin mentioned, but actually when I dug into the theme my site is using, it didn’t seem to make use of any of the thumbnail versions at all. So actually, the easiest thing to do was to iterate over all the folder/month combos and delete all the WordPress-generated files (e.g. only keeping the original). So far things look fine, so I recommend that option to anyone with a small amount of programming skill, I just needed to pattern match on “year/month/*[0-9]x[0-9]*jpg”. Got rid of over 1 million files and 65 GB worth of space…
I have managed my images for years by creating a helper function that would resize them on demand, things got a little bit easier by creating Twig filter in the Timber Template, this way when I design theme I just put in necessary parameters into the filter like so `{{ img_src | img_resize(width, height) }}` which is especially helpful with responsive images because you can create a different size for different devices with different pixel ratio as well as you can convert images to new formats such as “webp” to improve performance. But there is a pitfall when you doing it this way. When creating custom thumbnails you need to ensure that they get deleted when source image gets deleted, as well as that the custom crops feature is lost, unless you use the custom crop as a source image.
It gets even more difficult with new Gutenberg project because there is no way you can resize images without making additional API which would be resizing images via ajax calls.
I am pretty sure WordPress developers are aware of that problem but they are victims of their popularity and can’t solve that problem easily without doing radical restructuring of their codebase which can damage a lot of plugins and sites so they just postpone this problem every iteration, which will bite them in the ass eventually and people will start seeking a WordPress alternative unless they do something about it.
They could integrate cool library https://glide.thephpleague.com/ which would make thing much easier but as I mentioned earlier that is a more radical solution but a necessary solution that would break a lot of code.
Such problems are like cancers they have to be treated early otherwise you rich the point of no return, and I hope that WordPress developers realize that.
Hi. How can I limit the additional images sizes I created to only the relevant plugin? I have the following code to create image sizes for my custom slider plugin. But when I upload an image with another plugin, or the default media uploader, then these sizes are also created.
Thank you
function tsum_media_size_slider() {
add_image_size(‘Slider’,1200,400,true);
add_image_size(‘Slider Preview’,200,67,true);
}
add_action(‘after_setup_theme’, ‘tsum_media_size_slider’);
Hi,
This post should belong to any WordPress related documentation or book. Even my 1000 pages WP Bible doesn’t say anything about this issue. Thanks a lot.
Greetings from Fontainebleau, France.
It’s 2021 and I’m still itching with this problem, using Newsmag theme at the moment. Already disabled lots of thumbnail generations but the theme’s built-in search and mobile theme are both using smaller thumbnails….
Wish I knew about this before purchasing the theme years back