Almost every WordPress theme has a setup function hooked to after_setup_theme. This is the right place to declare what your theme supports — post thumbnails, HTML5 markup, title tags, custom logos, and more. Running this code at after_setup_theme ensures WordPress knows about your theme’s capabilities before it starts rendering anything.
Problem: How do you correctly register theme features — such as post thumbnails, custom menu locations, HTML5 support, and title tag management — in a WordPress theme?
Solution: Place all feature declarations inside an after_setup_theme action hook. It fires after WordPress has loaded the theme but before headers are sent, making it the correct place for add_theme_support() and register_nav_menus() calls.
add_action( 'after_setup_theme', 'mytheme_setup' );
function mytheme_setup() {
// Let WordPress manage the document title automatically
add_theme_support( 'title-tag' );
// Enable support for Post Thumbnails on posts and pages
add_theme_support( 'post-thumbnails' );
set_post_thumbnail_size( 1200, 628, true ); // hard-crop
// Register additional image sizes
add_image_size( 'blog-card', 480, 320, true );
add_image_size( 'hero', 1600, 600, true );
// HTML5 markup for search form, comment form, galleries, captions
add_theme_support( 'html5', [
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
] );
// Custom logo support
add_theme_support( 'custom-logo', [
'height' => 80,
'width' => 250,
'flex-width' => true,
'flex-height' => true,
] );
// Custom background colour/image
add_theme_support( 'custom-background', [
'default-color' => 'ffffff',
] );
// Make theme available for translation
load_theme_textdomain( 'mytheme', get_template_directory() . '/languages' );
// Register navigation menus
register_nav_menus( [
'primary' => __( 'Primary Menu', 'mytheme' ),
'footer' => __( 'Footer Menu', 'mytheme' ),
] );
}
To display the custom logo in a template:
if ( function_exists( 'the_custom_logo' ) && has_custom_logo() ) {
the_custom_logo();
} else {
echo '<a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html( get_bloginfo( 'name' ) ) . '</a>';
}
NOTE: Always check with current_theme_supports() before using a feature that requires add_theme_support(). Child themes inherit the parent's after_setup_theme callback, so you only need to add or override what is different — not redefine everything from scratch.