Himanshu SharmaSoftware engineer
Let’s talk

WordPress · Lesson 8 of 45

Images and the media library

Upload and manage images in the WordPress media library, write good alt text, and understand the image sizes WordPress creates and responsive srcset.

12 minContentUpdated 23 October 2026

By the end of this lessonAdd images that load fast and are accessible, and explain what WordPress does with every image you upload.

The media library

Media → Library holds every file uploaded to the site: images, PDFs, audio and video. You can upload there directly, or from the editor when you add an Image block. Each file gets a page in the library where you can edit its title, alt text, caption and description, and basic editing tools such as crop, rotate and scale.

What happens when you upload an image

To see exactly what WordPress does, we first create a test photo (1600 by 1000 pixels) with PHP's image functions, standing in for a photo from your camera:

php
<?php
$image = imagecreatetruecolor( 1600, 1000 );
imagefill( $image, 0, 0, imagecolorallocate( $image, 30, 120, 160 ) );
imagejpeg( $image, ABSPATH . 'lake.jpg', 85 );
echo "created lake.jpg, ", filesize( ABSPATH . 'lake.jpg' ) > 0 ? 'ok' : 'failed', "\n";
result
created lake.jpg, ok

Now upload it, as the dashboard would, with WP-CLI's media import:

bash
wp media import lake.jpg --title="Lake at dawn" --alt="Calm blue lake under a clear sky at dawn" --porcelain
result
4

--porcelain makes WP-CLI print only the new attachment's ID. Behind the scenes WordPress:

  1. copied the file into wp-content/uploads/ in a year/month folder for the month of the upload (2026/10 in the examples here);
  2. created an attachment post (an entry in wp_posts with post_type attachment) holding the title, alt text and caption;
  3. generated smaller copies of the image.
php
<?php
$id = (int) get_posts( [ 'post_type' => 'attachment', 'numberposts' => 1, 'fields' => 'ids' ] )[0];
$meta = wp_get_attachment_metadata( $id );
echo "original: {$meta['width']} x {$meta['height']}\n";
foreach ( $meta['sizes'] as $name => $size ) {
	printf( "%-13s %4d x %-4d %s\n", $name, $size['width'], $size['height'], $size['file'] );
}
echo "alt text: ", get_post_meta( $id, '_wp_attachment_image_alt', true ), "\n";
result
original: 1600 x 1000
medium         300 x 188  lake-300x188.jpg
large         1024 x 640  lake-1024x640.jpg
thumbnail      150 x 150  lake-150x150.jpg
medium_large   768 x 480  lake-768x480.jpg
1536x1536     1536 x 960  lake-1536x960.jpg
alt text: Calm blue lake under a clear sky at dawn

Five extra files from one upload, each in the same folder as the original. thumbnail is cropped to a square; the others keep the proportions and fit within a maximum width and height. You can change the first three in Settings → Media; themes and plugins can register more sizes. A size is only created when the original is bigger, which is why there is no 2048 copy of this 1600-pixel image.

Responsive images with srcset

When WordPress outputs an image, it lists the available sizes in a srcset attribute, so each browser downloads the smallest file that looks sharp on its screen:

php
<?php
$id = (int) get_posts( [ 'post_type' => 'attachment', 'numberposts' => 1, 'fields' => 'ids' ] )[0];
$html = wp_get_attachment_image( $id, 'large' );
foreach ( [ 'src', 'width', 'height', 'alt', 'loading', 'srcset', 'sizes' ] as $attribute ) {
	if ( preg_match( '/ ' . $attribute . '="([^"]*)"/', $html, $found ) ) {
		echo str_pad( $attribute, 8 ), str_replace( ', ', ",\n        ", $found[1] ), "\n";
	}
}
result
src     http://localhost:8080/wp-content/uploads/2026/10/lake-1024x640.jpg
width   1024
height  640
alt     Calm blue lake under a clear sky at dawn
loading lazy
srcset  http://localhost:8080/wp-content/uploads/2026/10/lake-1024x640.jpg 1024w,
        http://localhost:8080/wp-content/uploads/2026/10/lake-300x188.jpg 300w,
        http://localhost:8080/wp-content/uploads/2026/10/lake-768x480.jpg 768w,
        http://localhost:8080/wp-content/uploads/2026/10/lake-1536x960.jpg 1536w,
        http://localhost:8080/wp-content/uploads/2026/10/lake.jpg 1600w
sizes   auto,
        (max-width: 1024px) 100vw,
        1024px

Notice what you get for free:

  • width and height, so the browser reserves space and the page does not jump while the image loads;
  • the alt text you entered;
  • srcset and sizes, for responsive loading.

When you insert an image in the editor, the Image block outputs the same kind of markup. WordPress also adds loading="lazy" to images further down a page so they load only when needed (it leaves it off the first large image, which should load straight away). The sizes value begins with auto: for lazy-loaded images, browsers that support it work out the right size from the layout themselves.

Alt text

Alt text (the alt attribute) is read aloud by screen readers, shown if the image fails to load, and used by search engines. Write what the image means in its context:

  • A product photo: "Oak desk with two drawers, shown from the front".
  • A chart: the key finding, such as "Sales doubled between 2024 and 2026".
  • An image of text: the text itself.
  • A purely decorative image (a background flourish): leave alt empty, so screen readers skip it.

Avoid "image of" and file names like IMG_2041.jpg. Set alt text in the Image block's sidebar or in the media library.

A caption appears under the image on the page, visible to everyone; it complements alt text rather than replacing it. A featured image (set in the post sidebar) represents a post in listings and when shared on social media.

Keep images light

A modern phone photo can be 4000 pixels wide and several megabytes. WordPress scales very large images down to 2560 pixels on upload and creates smaller copies, but you should still:

  • resize photos to about the largest size they will be shown (often 1600 to 2000 pixels wide);
  • compress them (good tools keep quality while cutting the size by half or more);
  • prefer WebP or AVIF for photos where your audience's browsers support them, which is nearly everywhere now;
  • avoid uploading images that will only ever be shown small.

The performance lesson later in the course covers images further.

Common mistakes

  • Uploading huge original photos and slowing every page.
  • Empty or useless alt text on informative images.
  • Text baked into images (prices, buttons) that screen readers and search engines cannot read.
  • Deleting media still used in posts, leaving broken images; check where a file is used first.

Exercise

Upload a photo to your local site. Set its alt text, then insert it in a post with an Image block and a caption. View the page source in your browser and find the srcset attribute. How many sizes does it list?

Show one possible answer

After uploading a 3000-pixel-wide photo and inserting it at Large size, the page source shows an img with srcset listing several widths, for example 1024w, 300w, 768w, 1536w and 2048w, plus the alt you entered and a figcaption with the caption. The exact list depends on the photo's size and the sizes registered by the theme.

Key points

  • Every uploaded file becomes an attachment post, with the file stored under wp-content/uploads/year/month/.
  • WordPress creates several smaller copies of each image (thumbnail, medium, large and more) and uses srcset so browsers download a suitable size.
  • Alt text describes an image for people who cannot see it; leave it empty only for purely decorative images.
  • Resize and compress photos before uploading; a phone photo straight from the camera is far larger than any page needs.

Check yourself

1. Where does WordPress store uploaded files by default?
2. Why does WordPress create several sizes of each image?
3. What is good alt text for a photo of the shop's front door with opening hours on a sign?
4. When is empty alt text correct?