Display 3 posts with different HTML markup using a loop

The WordPress query object has an internal counter, current_post, which you can use to check the position of the post in the loop you are currently outputting, whether it’s the main query $wp_query or a custom query you create via WP_Query. The important thing to remember about current_post is that it’s zero indexed, the first post is 0, the second post is 1, etc..

Example, using the main query in a template:

while( have_posts() ):
    the_post();

    if( 0 == $wp_query->current_post ) {
        echo 'this is the first post';
        // markup for first post
    } elseif( 1 == $wp_query->current_post ) {
        echo 'this is the second post';
    } elseif( 2 == $wp_query->current_post ) {
        echo 'this is the third post';
    } else {
        echo 'this is > third post';
    }

endwhile;

If you create a new query via WP_Query, you do the same thing, except you reference the query object you created with your custom query:

$args = array(); // your custom query args
$custom_query = new WP_Query( $args );

while( $custom_query->have_posts() ):
    $custom_query->the_post();

    if( 0 == $custom_query->current_post ) {
        echo 'this is the first post';
    }
    // etc..

endwhile;