Skip to main content
WordPress made easy with the drag & drop Total WordPress Theme!Learn More

Make Yoast SEO Breadcrumbs Accessible

Last modified: November 8, 2023

By default the Yoast SEO breadcrumbs HTML output uses a <span> around every item and a suggested <p> element around the whole breadcrumbs trail. This is perfectly fine but it’s not the ideal output for the breadcrumbs. What’s a bit strange is if you were to inspect the breadcrumbs used on the Yoast SEO blog you would see that they’ve even modified the output of their yoast_breadcrumb function (or perhaps they are using their own custom code) so that it is more accessible.

The Aditus website has a really good article on how to make your breadcrumbs accessible which is what I am using as a guide to modify the Yoast breadcrumbs.

Step 1: Insert the Breadcrumbs “Correctly”

If you were to follow the Yoast documentation they suggest you insert your breadcrumbs in the following way:

if ( function_exists('yoast_breadcrumb') ) {
  yoast_breadcrumb( '<p id="breadcrumbs">','</p>' );
}

Rather you will want to use a <nav> element instead of the <p> tag and you will want to add an aria-label attribute to let screen readers know that this navigation element is the site breadcrumbs (instead of breadcrumbs some sites use the text “you are here:”. This is the code I suggest you use instead when adding the breadcrumbs to your site:

if ( function_exists('yoast_breadcrumb') ) {
  yoast_breadcrumb( '<nav aria-label="breadcrumbs" id="breadcrumbs">','</nav>' );
}

Using the [wpseo_breadcrumb] Shortcode?

If you are instead inserting the breadcrumbs using the shortcode I couldn’t find a good way to modify the output via a filter so my suggestion would be to simply wrap the shortcode inside a <nav> element like such:

<nav id="breadcrumbs" aria-label="breadcrumbs">[wpseo_breadcrumb]</nav>

Using the yoast-seo/breadcrumbs Gutenberg block?

And if you are using the Yoast SEO breadcrumbs block (which will be the case if you are using a FSE block theme) then you need to modify the output of the block which can be done with the following code:

// Modify the yoast-seo/breadcrumbs block output.
add_filter( 'render_block', function( $content, $block ) {
	if ( isset( $block['blockName'] ) && 'yoast-seo/breadcrumbs' === $block['blockName'] ) {
		$content = str_replace( '<div class="yoast-breadcrumbs">', '<nav class="yoast-breadcrumbs" aria-label="breadcrumbs">', $content );
		$content = rtrim( $content, '</div>' ) . '</nav>';
	}
	return $content;
}, 10, 2 );

If you have a look at the code you can see we are specifically overriding the following string:

<div class="yoast-breadcrumbs">

If Yoast ever changes the output this code may need adjusting. You could instead just wrap the default output in your new <nav> element which should never cause issues, but I didn’t like having a div inside my navigation element.

Step 2: Converting the Breadcrumbs into an Ordered List (ol)

As I mentioned at the beginning of the guide Yoast inserts every breadcrumb item inside a <span> but in order to provide the set of links structured as a hierarchy we’ll want to convert them into list items and wrap them inside an <ol> list.

Luckily this is very simple to do! Yoast provides us with 2 filters we can use to modify the wrapper of each item and also the outer wrapper of all items. Add the following code to your site to convert the Yoast breadcrumbs into an ordered list:

// Convert the Yoast Breadcrumbs output wrapper into an ordered list.
add_filter( 'wpseo_breadcrumb_output_wrapper', function() {
	return 'ol';
} );

// Convert the Yoast Breadcrumbs single items into list items.
add_filter( 'wpseo_breadcrumb_single_link_wrapper', function() {
	return 'li';
} );

Step 3: Modify/Remove the Separators

Now that we’ve added the proper wrappers to convert our breadcrumbs into an ordered list the Yoast separators end up in between our list items <li> which is incorrect HTML syntax so we’ll need to modify or remove our separators. There are a couple ways of doing this: we can modify the separators to also wrap them inside a list item or we can remove them completely and use CSS to insert a character between the items.

Option 1: Modify Separators

The first option is to keep our separators but wrap them inside <li> elements as well so that our HTML has proper syntax. We can do this using the following code:

add_filter( 'wpseo_breadcrumb_separator', function() {
    return '<li aria-hidden="true"> ► </li>';
} );

Notice that we’ve included an aria-hidden attribute this is to ensure that screen reader users don’t announce it as text.

Important: For some reason this filter will ONLY run if the “Separator between breadcrumbs” option in the Yoast settings panel is NOT empty. So if you removed the separator from in there this filter won’t do anything. And of course it’s possible to modify the separator via the Yoast SEO settings, but because we are inserting HTML I think it’s best to use the filter to ensure it always works.

Option 2: Remove Separators

If you want to remove the separators completely and use CSS to add some sort of symbol between your separators you can do so with the following code:

add_filter( 'wpseo_breadcrumb_separator', '__return_empty_string' );

It’s important to note that you can also remove the separator via the Yoast SEO settings panel which I actually recommend to do instead. When using the filter the Yoast SEO plugin is not checking if the value is empty or not before inserting the separator so it will technically insert a white space on your site. However, if you save an empty value in the settings panel it won’t do this. I recommend doing both though incase they ever change how the plugin works and decide they want to add a fallback value when someone saves an empty one.

Adding a new Seperator using CSS

Here is some CSS you could use to insert a forward slash between your items now that you’ve removed the default separator HTML.

#breadcrumbs li:not(:first-child)::before {
    content: "/";
    display: inline-block;
    margin: 0 5px;
}

Final Thoughts

Luckily the Yoast SEO plugin includes all the filters we need to properly modify the HTML output to make it more accessible, however, it would be nice to see them update the default output in the future. Perhaps they don’t want to update since so many websites use their plugin it could be a real pain for developers to go back and update their sites. But maybe they could include an on/off toggle (at least in the premium version) that you can enable to alter the default formatting to make it accessible.

Let me know in the comments if you have any issues or questions!

Comments

No comments yet. Why don't you kick off the discussion?

Leave a Reply

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

Learn how your comment data is processed by viewing our privacy policy here.