# Recent Posts Widget With Thumbnails

> Adds a "Recent Posts With Thumbnails" widget that lists your latest posts with a small featured image and optional date, for classic sidebars.

- Type: PHP
- Runs: Run everywhere
- Category: [Widgets](https://wpide.com/library/category/widgets/)
- Tags: widgets, recent-posts, thumbnails
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/recent-posts-with-thumbnails-widget/

## Code

```php
if ( ! class_exists( 'WPIDE_Recent_Posts_Thumbs_Widget' ) ) {
    class WPIDE_Recent_Posts_Thumbs_Widget extends WP_Widget {
        public function __construct() {
            parent::__construct( 'wpide_recent_thumbs', 'Recent Posts With Thumbnails', array(
                'description'                 => 'Your latest posts with their featured images.',
                'customize_selective_refresh' => true,
            ) );
        }

        public function widget( $args, $instance ) {
            $title  = isset( $instance['title'] ) && '' !== $instance['title'] ? $instance['title'] : 'Recent Posts';
            $title  = apply_filters( 'widget_title', $title, $instance, $this->id_base );
            $number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : 5;
            $posts  = get_posts( array(
                'numberposts'         => $number,
                'ignore_sticky_posts' => true,
                'no_found_rows'       => true,
                'post__not_in'        => is_singular() ? array( get_queried_object_id() ) : array(),
            ) );

            if ( ! $posts ) {
                return;
            }

            echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput -- markup from the theme.

            if ( '' !== (string) $title ) {
                echo $args['before_title'] . esc_html( $title ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput
            }

            echo '<ul class="wpide-recent-thumbs" style="list-style:none;margin:0;padding:0;">';

            foreach ( $posts as $item ) {
                echo '<li style="display:flex;gap:.75em;align-items:center;margin:0 0 .75em;">';

                if ( has_post_thumbnail( $item ) ) {
                    echo '<a href="' . esc_url( get_permalink( $item ) ) . '" style="flex:0 0 64px;" tabindex="-1" aria-hidden="true">' . get_the_post_thumbnail( $item, 'thumbnail', array( 'style' => 'display:block;width:64px;height:64px;object-fit:cover;border-radius:4px;', 'alt' => '' ) ) . '</a>';
                }

                echo '<span><a href="' . esc_url( get_permalink( $item ) ) . '">' . esc_html( get_the_title( $item ) ) . '</a>';

                if ( ! empty( $instance['show_date'] ) ) {
                    echo '<br /><small>' . esc_html( get_the_date( '', $item ) ) . '</small>';
                }

                echo '</span></li>';
            }

            echo '</ul>';
            echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput
        }

        public function form( $instance ) {
            $title     = isset( $instance['title'] ) ? $instance['title'] : '';
            $number    = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : 5;
            $show_date = ! empty( $instance['show_date'] );

            echo '<p><label for="' . esc_attr( $this->get_field_id( 'title' ) ) . '">Title:</label><input class="widefat" type="text" id="' . esc_attr( $this->get_field_id( 'title' ) ) . '" name="' . esc_attr( $this->get_field_name( 'title' ) ) . '" value="' . esc_attr( $title ) . '" /></p>';
            echo '<p><label for="' . esc_attr( $this->get_field_id( 'number' ) ) . '">Number of posts:</label> <input class="tiny-text" type="number" min="1" max="20" id="' . esc_attr( $this->get_field_id( 'number' ) ) . '" name="' . esc_attr( $this->get_field_name( 'number' ) ) . '" value="' . esc_attr( $number ) . '" /></p>';
            echo '<p><input type="checkbox" class="checkbox" id="' . esc_attr( $this->get_field_id( 'show_date' ) ) . '" name="' . esc_attr( $this->get_field_name( 'show_date' ) ) . '"' . checked( $show_date, true, false ) . ' /> <label for="' . esc_attr( $this->get_field_id( 'show_date' ) ) . '">Show post date</label></p>';

            return '';
        }

        public function update( $new_instance, $old_instance ) {
            return array(
                'title'     => isset( $new_instance['title'] ) ? sanitize_text_field( $new_instance['title'] ) : '',
                'number'    => isset( $new_instance['number'] ) ? max( 1, min( 20, absint( $new_instance['number'] ) ) ) : 5,
                'show_date' => ! empty( $new_instance['show_date'] ),
            );
        }
    }
}

add_action( 'widgets_init', function () {
    register_widget( 'WPIDE_Recent_Posts_Thumbs_Widget' );
} );
```

## Notes

Add it under Appearance > Widgets (as a Legacy Widget in the block widget editor).

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Recent Posts Widget With Thumbnails" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
