Latest posts block: style “read more” link as button
Published: – Leave a comment
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();
$dom->loadHTML(
'<html><meta charset="utf-8">' . $block_content . '</html>',
LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
);
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' ) ) {
continue;
}
$link = $anchor->getAttribute( 'href' );
break;
}
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>
</div>',
$link,
\esc_html__( 'Read more', 'my-textdomain' )
);
$read_more_dom = new DOMDocument();
$read_more_dom->loadHTML(
'<html><meta charset="utf-8">' . $template . '</html>',
LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
);
foreach ( $list_element->getElementsByTagName( 'div' ) as $div ) {
if ( ! \str_contains( $div->getAttribute( 'class' ), 'wp-block-latest-posts__post-excerpt' ) ) {
continue;
}
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)