Header Images for Categories
Adds an image picker to categories and shows the chosen image as a banner at the top of each category archive.
Opens WPIDE on
Code
// Adds a "Header image" picker to categories and shows the image at the top of the category archive.
$wpide_cat_image_size = 'full';
$wpide_cat_image_field = function ( $term_id = 0 ) {
$image_id = $term_id ? absint( get_term_meta( $term_id, 'wpide_header_image_id', true ) ) : 0;
$preview = $image_id ? wp_get_attachment_image( $image_id, 'medium', false, array( 'style' => 'max-width:300px;height:auto;display:block;margin-bottom:8px;' ) ) : '';
wp_nonce_field( 'wpide_cat_image', 'wpide_cat_image_nonce' );
echo '<div class="wpide-cat-image"><div class="wpide-cat-image__preview">' . $preview . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput -- core image markup.
echo '<input type="hidden" name="wpide_header_image_id" value="' . esc_attr( $image_id ) . '" />';
echo '<button type="button" class="button wpide-cat-image__choose">Choose image</button> ';
echo '<button type="button" class="button-link wpide-cat-image__remove"' . ( $image_id ? '' : ' hidden' ) . '>Remove image</button></div>';
};
add_action( 'category_add_form_fields', function () use ( $wpide_cat_image_field ) {
echo '<div class="form-field"><label>Header image</label>';
$wpide_cat_image_field();
echo '<p>Shown at the top of this category\'s archive page.</p></div>';
} );
add_action( 'category_edit_form_fields', function ( $term ) use ( $wpide_cat_image_field ) {
echo '<tr class="form-field"><th scope="row">Header image</th><td>';
$wpide_cat_image_field( $term->term_id );
echo '<p class="description">Shown at the top of this category\'s archive page.</p></td></tr>';
} );
$wpide_cat_image_save = function ( $term_id ) {
if ( ! isset( $_POST['wpide_cat_image_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['wpide_cat_image_nonce'] ), 'wpide_cat_image' ) || ! current_user_can( 'manage_categories' ) ) {
return;
}
$image_id = isset( $_POST['wpide_header_image_id'] ) ? absint( $_POST['wpide_header_image_id'] ) : 0;
if ( $image_id && wp_attachment_is_image( $image_id ) ) {
update_term_meta( $term_id, 'wpide_header_image_id', $image_id );
} else {
delete_term_meta( $term_id, 'wpide_header_image_id' );
}
};
add_action( 'created_category', $wpide_cat_image_save );
add_action( 'edited_category', $wpide_cat_image_save );
add_action( 'admin_enqueue_scripts', function ( $hook ) {
if ( ! in_array( $hook, array( 'edit-tags.php', 'term.php' ), true ) || 'category' !== get_current_screen()->taxonomy ) {
return;
}
wp_enqueue_media();
$script = <<<'JS'
jQuery( function ( $ ) {
var style = 'max-width:300px;height:auto;display:block;margin-bottom:8px;';
$( document ).on( 'click', '.wpide-cat-image__choose', function ( e ) {
e.preventDefault();
var box = $( this ).closest( '.wpide-cat-image' );
var frame = wp.media( { title: 'Header image', library: { type: 'image' }, multiple: false } );
frame.on( 'select', function () {
var img = frame.state().get( 'selection' ).first().toJSON();
var src = img.sizes && img.sizes.medium ? img.sizes.medium.url : img.url;
box.find( 'input' ).val( img.id );
box.find( '.wpide-cat-image__preview' ).html( $( '<img>', { src: src, alt: '', style: style } ) );
box.find( '.wpide-cat-image__remove' ).prop( 'hidden', false );
} );
frame.open();
} );
$( document ).on( 'click', '.wpide-cat-image__remove', function ( e ) {
e.preventDefault();
var box = $( this ).closest( '.wpide-cat-image' );
box.find( 'input' ).val( '' );
box.find( '.wpide-cat-image__preview' ).empty();
$( this ).prop( 'hidden', true );
} );
// The "Add New Category" form is submitted with AJAX; clear the picker afterwards.
$( document ).ajaxComplete( function ( event, xhr, options ) {
if ( options.data && 'string' === typeof options.data && -1 !== options.data.indexOf( 'action=add-tag' ) ) {
$( '#addtag .wpide-cat-image input' ).val( '' );
$( '#addtag .wpide-cat-image__preview' ).empty();
$( '#addtag .wpide-cat-image__remove' ).prop( 'hidden', true );
}
} );
} );
JS;
wp_add_inline_script( 'media-editor', $script );
} );
$wpide_cat_image_html = function () use ( $wpide_cat_image_size ) {
if ( ! is_category() || is_paged() ) {
return '';
}
$image_id = absint( get_term_meta( get_queried_object_id(), 'wpide_header_image_id', true ) );
return $image_id ? '<figure class="wpide-category-header" style="margin:0 0 1.5em;">' . wp_get_attachment_image( $image_id, $wpide_cat_image_size, false, array( 'style' => 'display:block;width:100%;height:auto;max-height:420px;object-fit:cover;border-radius:8px;', 'fetchpriority' => 'high', 'loading' => 'eager' ) ) . '</figure>' : '';
};
// Classic themes: above the first post.
add_action( 'loop_start', function ( $query ) use ( $wpide_cat_image_html ) {
static $done = false;
if ( $done || wp_is_block_theme() || ! $query->is_main_query() ) {
return;
}
$done = true;
echo $wpide_cat_image_html(); // phpcs:ignore WordPress.Security.EscapeOutput -- core image markup.
} );
// Block themes: before the archive title.
add_filter( 'render_block_core/query-title', function ( $content ) use ( $wpide_cat_image_html ) {
static $done = false;
if ( $done ) {
return $content;
}
$done = true;
return $wpide_cat_image_html() . $content;
} );
Notes
Classic themes get it above the posts, block themes before the archive title; it shows on the first page only.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.