plugin wraps the entire content

There are 2 major problems.

The first is that you output the opening div directly in the shortcode. Shortcodes must never echo or output directly, they always return a HTML string.

As a result, before the post content is even displayed, this has already been sent to the browser:

<div class="blog__grid">

You’re very lucky you’re wrapping your entire post content with this, otherwise you would have noticed that the opening tag is always at the beginning.

Not only that but:

  • AJAX requests that process this post will be broken
  • REST API endpoints will be broken
  • XMLRPC will be broken
  • Sitemaps will be broken
  • If your shortcode supported nested content, that content would appear after the shortcode, not inside it
  • If this shortcode appears inside another shortcode, it too will be broken
  • Parts of this shortcode will always appear at the start of the post content even if it isn’t at the start

You’ll get invalid XML errors or invalid JSON syntax errors for anything that doesn’t output HTML pages, and the order will be broken on those that do

But this leads to problem number 2. You never have a chance to output the closing tag

Look at this code:

            return $allposts;
        } ?>
    </div>

Notice that if posts are found, $allposts is returned, giving no opportunity for the closing </div> to be sent.

So instead:

  • Don’t output the opening and closing tags, assign them instead in a variable, lets call it $output;
  • Don’t return $allposts, add it to $output with $output .= $allposts;
  • End the function with return $output;

And if you must use code that outputs directly, wrap it in an output buffer.