In my last post, I showed how to load a specific block style in a different block and promised that I will show you how exactly I used it for the latest posts block. Since the “read more” link on this block is, by default, just a plain text link, I want to modify it to be styled as a regular button without needing to add custom CSS to style it this way.

I’m a fan of DOMDocument when it comes to add specific HTML at a specific position. Thus, I used it here. First I select every list item, as every latest post is within its own list item. Inside this list item, there are potentially multiple links, which I iterate through. In my case, I have only enabled the link of the title, so I explicitly check for the existence of the class wp-block-latest-posts__post-title and ignore this link element. If you also link your thumbnail to the post, you may need to extend this check.

After that, I use the link of the original “read more” link and replace its markup with a custom button(s) block.

And last but not least, as seen in my previous post, I enqueue the button block stylesheet to make sure the custom added “read more” button is properly designed.

This is what the code looks like in the end:

 * Add a read more link as button and remove possibly existing ones.
 * @param	string	$block_content Block content
 * @return	string Updated block content
function my_set_read_more_link( string $block_content ): string {
	\libxml_use_internal_errors( true );
	$dom = new \DOMDocument();
		'<html><meta charset="utf-8">' . $block_content . '</html>',
	foreach ( $dom->getElementsByTagName( 'li' ) as $list_element ) {
		$link = '';
		foreach ( $list_element->getElementsByTagName( 'a' ) as $anchor ) {
			if ( ! \str_contains( $anchor->getAttribute( 'class' ), 'wp-block-latest-posts__post-title' ) ) {
			$link = $anchor->getAttribute( 'href' );
		if ( ! empty( $link ) ) {
			$template = \sprintf(
				'<div class="wp-block-buttons">
					<div class="wp-block-button is-read-more-button"><a class="wp-block-button__link wp-element-button" href="%1$s">%2$s</a></div>
				\esc_html__( 'Read more', 'my-textdomain' )
			$read_more_dom = new DOMDocument();
				'<html><meta charset="utf-8">' . $template . '</html>',
			foreach ( $list_element->getElementsByTagName( 'div' ) as $div ) {
				if ( ! \str_contains( $div->getAttribute( 'class' ), 'wp-block-latest-posts__post-excerpt' ) ) {
				foreach ( $div->getElementsByTagName( 'a' ) as $anchor ) {
					$div->removeChild( $anchor );
				$read_more_node = $dom->importNode( $read_more_dom->documentElement->firstChild->nextSibling, true ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
				$div->appendChild( $read_more_node );
	$block_content = $dom->saveHTML( $dom->documentElement->firstChild->nextSibling ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
	\wp_enqueue_style( 'wp-block-button' );
	\libxml_use_internal_errors( false );
	return $block_content;

\add_filter( 'render_block_core/latest-posts', 'my_set_read_more_link' );
Code language: PHP (php)

Leave a Reply

Your email address will not be published. Required fields are marked *