Shortcodes for simple post lists in WordPress

Recently, I worked on my WordPress theme for KeesTalksTech. To gain performance, I need to rely less on plugins, that's why I needed a simple way to show small lists of posts in my sidebar.

I've created 2 WordPress short codes: one that shows recent posts, used in the new section and one that shows specific posts, used in the highlights section.

This is how the new and highlights sections look.

If you want to use these shortcodes, just copy the code into your functions.php .

Thumbnail Sizes

First, we must add support for thumbnail sizes. I'm using 70x70 for small screens and 140x140 for HD.

add_image_size('widget-tn',    140, 140, true);
add_image_size('widget-tn-sm',  70,  70, true);

Fun fact: when WordPress generates the thumbnail, it will include all the relevant sizes in the srcset. In my case that was even more than these two! The browser will decide which image to show.

A 'latest' shortcode

Let's look at the code:

<?php

function ktt_sh_latest($atts)
{
    ob_start();

    $top = 5;
    if (!empty($atts['top'])) {
        $top = $atts['top'];
    }

?><ul class="latest posts posts-widget">
        <?php
        $recent_posts = wp_get_recent_posts(array(
            'numberposts' => $top, // Number of recent posts thumbnails to display
            'post_status' => 'publish' // Show only the published posts
        ));
        foreach ($recent_posts as $post) : ?>
            <li>
                <a href="<?php echo get_permalink($post['ID']) ?>">
                    <?php echo get_the_post_thumbnail($post['ID'], 'widget-tn'); ?>
                    <span class="title"><?php echo $post['post_title'] ?></span>
                </a>
            </li>
        <?php endforeach;
        wp_reset_query(); ?>
    </ul>
<?php

    $content = ob_get_contents();
    ob_end_clean();
    return $content;
}

add_shortcode('latest', 'ktt_sh_latest');

The HTML generated by the short code is minimal, which makes styling easier. Linking to the post is done by a simple anchor.

The default value for top is 5, but you can change the number by specifying it in the shortcode:

[latest top="3"]

A 'highlights' shortcode

The highlights shortcode works very similar:

<?php

function ktt_sh_highlights($atts)
{
    ob_start();

    $ids = explode(',', $atts['ids']);

?><ul class="highlights posts-widget">
        <?php
        $recent_posts = wp_get_recent_posts(array('include' => $ids));
        foreach ($recent_posts as $post) : ?>
            <li>
                <a href="<?php echo get_permalink($post['ID']) ?>">
                    <?php echo get_the_post_thumbnail($post['ID'], 'widget-tn'); ?>
                    <span class="title"><?php echo $post['post_title'] ?></span>
                </a>
            </li>
        <?php endforeach;
        wp_reset_query(); ?>
    </ul>
<?php

    $content = ob_get_contents();
    ob_end_clean();
    return $content;
}

add_shortcode('highlights', 'ktt_sh_highlights');

We can use it like this:

[highlights ids="5767,4997,4849,4146,4774,4681,4427,4219,3521,2857"]

What about styling?

Let's use CSS grid to make styling easier:


.posts-widget {
  margin: 0;
  padding: 0;
  list-style: none;
}


.posts-widget li a {
  display: grid;
  grid-template-columns: 70px auto;
  column-gap: var(--gutter);
  font-weight: 700;
  margin-bottom: 20px;
  padding-bottom: 20px;
  border-bottom: #eee;
  background-color: transparent;
  text-decoration: none;
  color: inherit;
}

.posts-widget li:last-child a {
  border-bottom: none;
}

.posts-widget li a * {
  align-self: center;
}

.posts-widget li a img {
  border-radius: 8px;
  vertical-align: bottom;
  max-width: 100%;
  height: auto;
}

.entry-content .posts-widget li {
  list-style: none;
  margin: 0;
  padding: 0;
}

.entry-content ul.posts-widget > li > a {
  border-bottom: none;
  margin-bottom: 0;
  /* very specific to my theme: */
  box-shadow: none !important;
}

Note: I'm using Destyle.css to reset my styles.

Interactive example

The following articles are generated by adding [latest top="3"] to a paragraph in a post:

Why shortcodes?

I settled on shortcodes, because they are:

  • Easily added to the theme and require no installation.
  • Modifiable for future needs: just update your theme if you must (I tie the styling to the theme as well).
  • Versatile, as we can use them in posts, descriptions and widgets.
expand_less