Tips・WordPress templates and fetching posts

Displaying featured images, and fallback images

How to output featured images in your theme. Covers specifying sizes with the_post_thumbnail, fallback images when none is set, adding your own sizes, and what to do when the "Featured image" panel doesn't appear.

Featured images (thumbnails) are output with the_post_thumbnail(). Three things to get right: enabling it in the theme, specifying a size, and handling the case where none is set.

<?php the_post_thumbnail('large'); ?>

1. First, enable it in the theme

If the “Featured image” panel isn’t in the editing screen, your theme doesn’t support it yet. Add one line to functions.php.

add_theme_support('post-thumbnails');

For custom post types, include 'thumbnail' in supports when registering. Forget it and you end up with the panel on posts but not on products.

register_post_type('shohin', [
  'supports' => ['title', 'editor', 'thumbnail'],   // ← thumbnail
  // …
]);
Theme developmentCreating "products" with a custom post typeHow to register custom post types, in this lesson of the theme development course

2. Specify a size

The first argument of the_post_thumbnail() is the size name. Leave it out and you get the small post-thumbnail size, so make specifying it a habit.

ValueMeaning
'thumbnail'Thumbnail (150×150 by default, cropped)
'medium'Medium (300px wide by default)
'large'Large (1024px wide by default)
'full'The original uploaded size
[600, 400]Picks the closest thing to 600 wide by 400 tall

You can change the numbers under “Settings” → “Media.” Note that WordPress picks from the sizes it has already generated, so lining up oversized full images in a list makes it heavy.

To add a class, pass an array as the second argument.

<?php the_post_thumbnail('medium', ['class' => 'card-image']); ?>

3. Don’t let a missing image break the layout (fallbacks)

Featured images are sometimes just not there—and one missing image in an archive throws the whole look off. Branch on has_post_thumbnail().

<?php if (has_post_thumbnail()) : ?>
  <?php the_post_thumbnail('medium', ['class' => 'card-image']); ?>
<?php else : ?>
  <img class="card-image"
       src="<?php echo esc_url(get_theme_file_uri('images/no-image.png')); ?>"
       alt="" width="600" height="400">
<?php endif; ?>

get_theme_file_uri() returns the URL of a file in your theme (the same idea as get_template_directory_uri() . '/images/no-image.png', but it handles child themes).

.card-image {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

When you just want the URL

For background images and OG tags, use the function that returns a URL.

<?php $url = get_the_post_thumbnail_url(get_the_ID(), 'large'); ?>
<?php if ($url) : ?>
  <div class="hero" style="background-image: url('<?php echo esc_url($url); ?>');"></div>
<?php endif; ?>

To output the featured image of a different post outside the loop, use the form that takes an ID: get_the_post_thumbnail($post_id, 'medium').

Making linked cards in an archive

<article class="card">
  <a href="<?php the_permalink(); ?>">
    <?php if (has_post_thumbnail()) : ?>
      <?php the_post_thumbnail('medium', ['class' => 'card-image']); ?>
    <?php endif; ?>
    <h2><?php the_title(); ?></h2>
  </a>
</article>

Wrapping the image and title in a single link widens the clickable area and makes it easier to use.

Adding your own sizes

When the standard sizes don’t fit—“I want archive images cropped to 600×400”—add your own.

add_theme_support('post-thumbnails');
add_image_size('card', 600, 400, true);   // fourth argument true = crop
<?php the_post_thumbnail('card'); ?>
  • Fourth argument truecrops to exactly that size (good for archive cards)
  • Fourth argument falsescales down keeping the aspect ratio (nothing overflows, but heights vary)

Where does the alt attribute come from?

The alt attribute in the_post_thumbnail() comes from the “Alternative Text” you entered in the media library. Leave it empty and you get alt="".

  • Ideally, make it a practice to enter descriptive text at upload time
  • For decorative images, alt="" is the right answer (it’s excluded from screen readers)

Using it for og:image

Featured images can also serve as the thumbnail when someone shares your page.

<?php
$og = is_singular() && has_post_thumbnail()
  ? get_the_post_thumbnail_url(get_the_ID(), 'large')
  : get_theme_file_uri('images/og-default.png');
?>
<meta property="og:image" content="<?php echo esc_url($og); ?>">
TipsSet up OGP (how it looks when shared)How OG tags work, and how to check them

Summary

  1. When the panel is missing, use add_theme_support('post-thumbnails'); for custom post types, 'thumbnail' in supports
  2. Always specify a size ('medium', 'large' and so on). full in an archive is heavy
  3. Branch on has_post_thumbnail() and show a fallback at the same aspect ratio
  4. For just the URL, get_the_post_thumbnail_url(). For your own sizes, add_image_size() (existing images need regenerating)

Images shape the impression an archive makes. Deciding “what happens when there isn’t one” keeps things from falling apart once the site is live.

FAQ

The "Featured image" panel doesn't appear in the editing screen.
Your theme doesn't support featured images yet. Add add_theme_support('post-thumbnails'); to functions.php. For custom post types, include 'thumbnail' in register_post_type's supports.
I want a fallback image when no featured image is set.
Branch on has_post_thumbnail(). The standard approach is the_post_thumbnail() when true, and an img tag pointing at a no-image file in your theme when false.
I only want the featured image's URL.
get_the_post_thumbnail_url(get_the_ID(), 'large') returns the URL as a string. You can use it for CSS backgrounds and og:image.
The size I added with add_image_size isn't being used.
add_image_size only affects images uploaded after you added it. Existing media has no file at that size, so you need a thumbnail-regeneration plugin to rebuild them.