SponsoredHosinger Special Offer

WP WordPress Theme Development

Build classic and block WordPress themes from scratch: the template hierarchy, The Loop, the_title() and the_content(), template parts, menus, the Customizer, child themes and theme.json.

Featured Images and Image Sizes

WordPress Theme Development Lesson 19 of 30 ~4 min read

Overview

Featured images are printed with the_post_thumbnail(), which outputs a responsive <img> with srcset, lazy loading and the right alt text — provided your theme registers image sizes that match its layout.

Turning featured images on

You added add_theme_support( 'post-thumbnails' ) in lesson 11. That makes the Featured Image panel appear in the editor. Now display it.

Displaying the image

<?php if ( has_post_thumbnail() ) : ?>
    <figure class="post-thumbnail">
        <?php
        the_post_thumbnail(
            'large',
            array(
                'class'   => 'post-thumbnail__img',
                'loading' => 'eager', // The first image on a single post is the main content.
            )
        );
        ?>
        <?php if ( get_the_post_thumbnail_caption() ) : ?>
            <figcaption><?php the_post_thumbnail_caption(); ?></figcaption>
        <?php endif; ?>
    </figure>
<?php endif; ?>

Always check has_post_thumbnail() first, otherwise posts without an image leave an empty <figure> in the layout.

Built-in sizes

NameDefault sizeTypical use
thumbnail150 × 150, croppedSmall square avatars and lists
mediumup to 300 × 300In-content images
medium_largeup to 768 wideCards and tablets
largeup to 1024 × 1024Single post header
fullOriginal uploadHero images

Registering your own sizes

A card grid that needs every image exactly 600 × 400 should not rely on CSS squashing a random upload. Register a hard-cropped size:

<?php
function gdc_starter_image_sizes() {
    // name, width, height, crop
    add_image_size( 'gdc-card', 600, 400, true );     // Cropped to exactly 600 × 400.
    add_image_size( 'gdc-hero', 1920, 800, true );
    add_image_size( 'gdc-wide', 1200, 0, false );     // 1200 wide, any height.

    set_post_thumbnail_size( 600, 400, true );        // The 'post-thumbnail' default.
}
add_action( 'after_setup_theme', 'gdc_starter_image_sizes' );

// Offer the new sizes in the editor's image size dropdown.
function gdc_starter_image_size_names( $sizes ) {
    return array_merge(
        $sizes,
        array( 'gdc-card' => esc_html__( 'Card (600×400)', 'gdc-starter' ) )
    );
}
add_filter( 'image_size_names_choose', 'gdc_starter_image_size_names' );

With crop set to true, WordPress crops from the centre to the exact dimensions. Pass an array such as array( 'center', 'top' ) to keep faces in portraits.

Watch out: New sizes are only generated for images uploaded after you add them. Use the Regenerate Thumbnails plugin or wp media regenerate (WP-CLI) to create them for existing images.

Responsive images for free

the_post_thumbnail() prints a srcset listing every generated size, and a sizes attribute. The browser downloads the smallest file that fills the space — a phone never downloads your 1920 px hero. Help it by describing your layout:

<?php
the_post_thumbnail(
    'gdc-card',
    array(
        // Full width on phones, a third of the screen on desktops.
        'sizes' => '(max-width: 600px) 100vw, 33vw',
    )
);

Getting the image URL

For a CSS background, you need the URL rather than an <img> tag:

<?php $hero = get_the_post_thumbnail_url( get_the_ID(), 'gdc-hero' ); ?>

<section class="hero" <?php if ( $hero ) : ?>style="background-image: url('<?php echo esc_url( $hero ); ?>');"<?php endif; ?>>
    <?php the_title( '<h1>', '</h1>' ); ?>
</section>
Tip: Prefer an <img> over a CSS background whenever the image is content. Background images get no alt text, no srcset and no lazy loading.

Practice

  • Register a gdc-card size, regenerate thumbnails, and use it in template-parts/content.php.
  • View the page source and find the srcset WordPress generated.
  • Set a caption on a featured image and display it in a <figcaption>.
Create a free account to save which lessons you've finished. Save my progress