Change the WordPress Excerpt […] to a Read More Link

WordPress ends every automatic excerpt with […], which tells the reader there is more but gives them nothing to click. This snippet changes the WordPress default excerpt […] to an ellipsis followed by a Read more link to the post.

The link always points at the post the excerpt belongs to, also in widgets and custom queries outside the main loop, and screen readers hear which post it opens.

The snippet

<?php
/**
 * Replace the WordPress excerpt "[…]" with a "Read more" link to the post.
 */

// ===== Config =====
function dpc_excerpt_more_text() {
	return __( 'Read more', 'dpc' ); // Link text.
}
// ===== End of config =====

// Remember which post the excerpt is being built for; excerpt_more itself does not get it.
add_filter( 'get_the_excerpt', 'dpc_excerpt_more_remember_post', 9, 2 );

function dpc_excerpt_more_remember_post( $excerpt, $post = null ) {
	$GLOBALS['dpc_excerpt_more_post'] = $post;
	return $excerpt;
}

add_filter( 'excerpt_more', 'dpc_excerpt_more' );

function dpc_excerpt_more( $more ) {
	$post = get_post( $GLOBALS['dpc_excerpt_more_post'] ?? null );
	if ( ! $post ) {
		return $more;
	}

	$text  = dpc_excerpt_more_text();
	$title = html_entity_decode( wp_strip_all_tags( get_the_title( $post ) ), ENT_QUOTES, get_bloginfo( 'charset' ) );

	return sprintf(
		'&hellip; <a class="dpc-read-more" href="%1$s" aria-label="%2$s">%3$s</a>',
		esc_url( get_permalink( $post ) ),
		/* translators: 1: link text, 2: post title. */
		esc_attr( sprintf( __( '%1$s: %2$s', 'dpc' ), $text, $title ) ),
		esc_html( $text )
	);
}

How it works

  • When a post has no hand-written excerpt, wp_trim_excerpt() cuts the content and appends the value of the excerpt_more filter. The snippet returns &hellip; and the link instead of [&hellip;].
  • excerpt_more does not say which post is being trimmed, and get_the_permalink() without an argument reads the global post. Outside the loop that can be a different post. The get_the_excerpt callback at priority 9 remembers the real post first, and the link is built for that post.
  • The URL goes through esc_url() and the text through esc_html().
  • Many “Read more” links in a list sound the same to a screen reader. The aria-label starts with the visible text and adds the post title, for example “Read more: Hello world”.
  • The link has the class dpc-read-more for styling. It no longer has rel="nofollow": these are links to your own posts, and search engines should follow them.

Add it with Scripts Organizer

In Scripts Organizer go to Code Blocks → Add New and give the block a name. Set Trigger location to Everywhere, tick PHP under Script location, paste the code into the PHP editor, edit the config and publish. Leave Action/Hook empty.

The same code also works unchanged in a small plugin or an mu-plugin.

Customise it

  • Other wording: change the string in dpc_excerpt_more_text(). It is translatable with the dpc text domain.
  • No ellipsis: remove &hellip; at the start of the format string, but keep a space before <a.
  • Shorter or longer excerpts: see Change the Default Excerpt Length in WordPress.

Gotchas

  • Hand-written excerpts are not trimmed, so they get no link. Show a separate link in your template if you need one there too.
  • The block themes’ Post Excerpt block has its own More text setting. When it is filled in, the block hides this link so only one is shown.
  • Themes that already add a Read more button below the excerpt will now show two links; remove one of them.
  • The link also appears in RSS feeds that use excerpts, which is usually what you want.

The older version of this post printed get_the_permalink() unescaped, linked to the global post, had no space before the link and added rel="nofollow".

In the Scripts Organizer library Import it with one click from Scripts Organizer.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You’ll also get DPlugins product updates. No spam, and you can unsubscribe anytime.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You'll also get DPlugins product updates. No spam, and you can unsubscribe anytime.