SponsoredHosinger Special Offer

WP WordPress Theme Development

Build classic and block WordPress themes from scratch: the template hierarchy, The Loop, the_title() and the_content(), template parts, menus, the Customizer, child themes and theme.json.

Template Tags: the_title() and the_content()

WordPress Theme Development Lesson 7 of 30 ~6 min read

Overview

Template tags such as <?php the_title(); ?> and <?php the_content(); ?> are WordPress functions that print one piece of the current post — and understanding exactly what each one does to your content is what makes a template correct rather than merely working.

The two you will use on every template

<?php while ( have_posts() ) : the_post(); ?>

    <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

        <h1 class="entry-title"><?php the_title(); ?></h1>

        <div class="entry-content">
            <?php the_content(); ?>
        </div>

    </article>

<?php endwhile; ?>

Both must run inside the Loop, after the_post(). That call is what tells them which post is "current".

the_title() in depth

the_title() takes three optional parameters: text to print before the title, text to print after it, and whether to echo.

<?php
// the_title( $before, $after, $display )

// Wrap the title in a heading — nothing is printed if the title is empty.
the_title( '<h1 class="entry-title">', '</h1>' );

// Make the title a link on archive pages.
the_title(
    sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ),
    '</a></h2>'
);
Tip: Passing the wrapper as $before and $after is better than hard-coding <h1> around the call. If a post has no title, WordPress prints nothing at all — no empty <h1></h1> that screen readers would announce.

Behind the scenes, the_title() runs the title through the the_title filter. Plugins use that filter, and WordPress itself uses it to add "Private:" or "Protected:" in front of restricted posts. That is why you call the function rather than reading $post->post_title directly.

the_content() in depth

the_content() does far more than print text. It runs the stored post content through the the_content filter, which in turn:

  • Renders blocks — turning stored block comments into real HTML.
  • Runs shortcodes, so [gallery] becomes a gallery.
  • Converts bare URLs on their own line into embeds — a YouTube link becomes a video.
  • Adds <p> tags around paragraphs with wpautop() for content written in the classic editor.
  • Adds responsive srcset and lazy-loading attributes to images.
Watch out: If you print $post->post_content directly, none of that happens. Shortcodes show as raw [gallery] text and blocks show as HTML comments.

It also handles the More tag. On archive pages, content above <!--more--> is shown with a "Continue reading" link. Customise the link text with the first parameter:

<?php
the_content(
    sprintf(
        /* translators: %s: post title, only visible to screen readers */
        esc_html__( 'Continue reading %s', 'gdc-starter' ),
        '<span class="screen-reader-text">' . esc_html( get_the_title() ) . '</span>'
    )
);

And when a post is split into pages with the Page Break block, the_content() shows only the current page. Add wp_link_pages() right after it so readers can reach the other pages:

<div class="entry-content">
    <?php
    the_content();

    wp_link_pages(
        array(
            'before' => '<nav class="page-links">' . esc_html__( 'Pages:', 'gdc-starter' ),
            'after'  => '</nav>',
        )
    );
    ?>
</div>

the_ functions versus get_the_ functions

Almost every template tag comes in two versions. This is the most important pattern in this lesson.

Prints (echoes)Returns a valueUse the return version when
the_title()get_the_title()You need the title inside an attribute, a string, or a condition.
the_permalink()get_permalink()You are building a URL or passing it to another function.
the_excerpt()get_the_excerpt()You want to trim or test the excerpt first.
the_ID()get_the_ID()You are passing the ID to another function.
the_content()apply_filters( 'the_content', get_the_content() )Rarely — get_the_content() alone skips the filters above.

Here is the difference in practice. The first line is wrong; the second is correct:

<!-- Wrong: the_title() echoes immediately, so the title appears
     BEFORE the <img> tag and the alt attribute is empty. -->
<img src="cover.jpg" alt="<?php echo the_title(); ?>">

<!-- Right: get_the_title() returns the string, escaped for an attribute. -->
<img src="cover.jpg" alt="<?php echo esc_attr( get_the_title() ); ?>">

Escaping: when to wrap a template tag

Functions that echo — the_title(), the_content(), the_permalink() — handle their own output safely for their usual context. Functions that return hand you raw data, and you must escape it for where it is going:

Output is going intoEscape with
Normal HTML textesc_html( get_the_title() )
An HTML attributeesc_attr( get_the_title() )
A URL attribute (href, src)esc_url( get_permalink() )

Lesson 25 covers escaping in depth. The habit to build now: **every echo gets an escaping function**.

Other everyday template tags

TagPrints
the_ID()The post ID, e.g. 42.
the_permalink()The post URL.
the_excerpt()The manual excerpt, or the first 55 words with HTML removed.
post_class()class="..." with status, type, format and category classes.
body_class()class="..." for <body>, describing the whole page.
edit_post_link()An "Edit" link, shown only to users allowed to edit the post.

Using a template tag outside the Loop

The get_ versions accept a post ID or post object, so they work anywhere — in a sidebar, a widget, or a function:

<?php
$about_page = get_page_by_path( 'about' );

if ( $about_page ) {
    printf(
        '<a class="about-link" href="%1$s">%2$s</a>',
        esc_url( get_permalink( $about_page ) ),
        esc_html( get_the_title( $about_page ) )
    );
}

Common mistakes

  • Writing <?php echo the_title(); ?>. The echo is redundant — the_title() already prints and returns nothing.
  • Using get_the_content() and printing it, which skips shortcodes and blocks.
  • Calling the_title() before the_post() has run, which prints the title of the wrong post or none.

Practice

  • Create single.php with the_title() wrapped through its $before and $after parameters and the_content() followed by wp_link_pages().
  • Add a post with a [gallery] shortcode. Print it once with the_content() and once with echo $post->post_content; and compare.
  • Build an image alt attribute from get_the_title() and confirm it is escaped with esc_attr().
Create a free account to save which lessons you've finished. Save my progress