WordPress中的短代码问题

I've created a shortcode in WordPress that I use to call latest blog posts. I've wrapped title and content with <h2> and <p>, but this is not being applied. The html is being generated but without tags where I want. What am I writing wrong?

This is my code:

<?php 

//blog posts shortcode

function my_recent_post()
 {
  global $post;

  $html = "";

  $my_query = new WP_Query( array(
       'post_type' => 'post',
       'cat' => '4',
       'posts_per_page' => 1
  ));

  if( $my_query->have_posts() ) : while( $my_query->have_posts() ) : $my_query->the_post();

       $html .= "<span>" . the_post_thumbnail( 'medium', array( 'class' => 'img-responsive') ) . "</span>";
       $html .= "<h2>" . the_title() . "</h2>";
       $html .= "<p>" . the_excerpt() . "</p>";

  endwhile; endif;

  return $html;
 }
 add_shortcode( 'blog', 'my_recent_post' );    
 ?>

The problem is that you are using function that print the html instead returns it. Try this

//blog posts shortcode
add_shortcode( 'blog', 'my_recent_post' );    

function my_recent_post() {
    global $post;

    $html = "";

    $my_query = new WP_Query( array(
        'post_type' => 'post',
        'cat' => '4',
        'posts_per_page' => 1
    ));

   if( $my_query->have_posts() ) : while( $my_query->have_posts() ) : $my_query->the_post();

       $html .= "<span>" . get_the_post_thumbnail( $post->ID, 'medium', array( 'class' => 'img-responsive') ) . "</span>";
       $html .= "<h2>" . get_the_title() . "</h2>";
       $html .= "<p>" . get_the_excerpt() . "</p>";

  endwhile; endif;

  return $html;
}