How to create a shortcode with html and php code

You can use PHPs output buffering, using ob_start to turn on the buffering and ob_get_clean to get and delete the current output buffering.

So going by your code it would look like this

function blogPost(){
    ob_start();
?>
    <section class="blog container spacer">
        <article class="blog__list">
            <div class="glide-blog">
                <div class="glide__arrows" data-glide-el="controls">
                    <button class="glide__arrow glide__arrow--left" data-glide-dir="<">&lt;</button>
                    <button class="glide__arrow glide__arrow--right" data-glide-dir=">">&gt;</button>
                </div>
                <div class="glide__track" data-glide-el="track">
                    <ul class="glide__slides">
                        <?php 
                        $the_query = new WP_Query( 'posts_per_page=3' );

                        // Start our WP Query
                        while ($the_query->have_posts()) : $the_query->the_post(); 
                        ?>
                        <li class="glide__slide"><?php the_post_thumbnail('medium'); ?>
                            <a href="<?php the_permalink() ?>" class="new-article__main-title"><?php the_title(); ?></a>
                        </li>
                        <?php 
                        // Repeat the process and reset once it hits the limit
                        endwhile;
                        wp_reset_postdata();
                        ?>
                    </ul>
                </div>
            </div>
        </article>
    </section>
<?php
    return ob_get_clean();
}
add_shortcode('blog_shortcode','blogPost');

Notice that instead add_action we now have add_shortcode, add_shortcode is the function you use to create custom shortcodes.

I also fixed a few issues with the code.

  • $the_query -> have_posts() should not contain spaces between the “arrow”, it should be like this $the_query->have_posts().
  • Added a few missing closing </div> tags.
  • Corrected indentation based on the missing </div> tags