New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add option to make breadcrumbs a nav element. #12079
Conversation
Aside: on yoast.com the breadcrumbs are already wrapped in a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CR done. I've asked @moorscode to take a look at the option addition part.
frontend/class-breadcrumbs.php
Outdated
|
||
// Override the before and after strings when breadcrumbs are set to be within a `<nav>` element. | ||
if ( WPSEO_Options::get( 'breadcrumbs-nav-wrapper' ) === true ) { | ||
$before = '<nav aria-label="' . __( 'Breadcrumbs', 'wordpress-seo' ) . '"' . self::get_output_id() . self::get_output_class() . '>'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of making the methods static you should be able to call this by $instance->get_output_it()
and $instance->get_output_class()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have concerns about overwriting the $before
. I think it will be better to extend the $output
. By overwriting the $before
and $after
you can possibly break implementations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The KB article instructed to use the following snippet for ages:
if ( function_exists( 'yoast_breadcrumb' ) ) {
yoast_breadcrumb( '<p id="breadcrumbs">', '</p>' );
}
So we can't add a <nav>
inside a paragraph or any other element that could produce invalid markup. At this point there are two options:
- either override the
$before
and$after
- or wrap the entire output with a
<nav>
but even in this case there's the risk the markup won't be optimal
Open to suggestions 🙂 but as a general consideration, there are too many options and too many <span>
, I'd rather simplify all the things.
P.S. there's also the wpseo_breadcrumb_output_wrapper
filter problem to take into consideration.
frontend/class-breadcrumbs.php
Outdated
*/ | ||
private function wrap_breadcrumb() { | ||
if ( is_string( $this->output ) && $this->output !== '' ) { | ||
$output = '<' . $this->wrapper . $this->get_output_id() . $this->get_output_class() . '>' . $this->output . '</' . $this->wrapper . '>'; | ||
$output = '<' . $this->wrapper . self::get_output_id() . self::get_output_class() . '>' . $this->output . '</' . $this->wrapper . '>'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would love to see this change reverted. You can access private with self::$instance->get_output_id()
/ self::$instance->get_output_class()
@@ -58,6 +58,7 @@ class WPSEO_Option_Titles extends WPSEO_Option { | |||
'breadcrumbs-prefix' => '', // Text field. | |||
'breadcrumbs-searchprefix' => '', // Text field. | |||
'breadcrumbs-sep' => '»', // Text field. | |||
'breadcrumbs-nav-wrapper' => false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if an option is the right solution for this.
If it is for accessibility, we might consider doing this by default and give the user the possibility to disable it by a hook. /cc @moorscode
frontend/class-breadcrumbs.php
Outdated
@@ -1043,7 +1055,7 @@ private function get_output_id() { | |||
* | |||
* @return string | |||
*/ | |||
private function get_output_class() { | |||
private static function get_output_class() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can undo this change (see earlier comments)
frontend/class-breadcrumbs.php
Outdated
@@ -1024,7 +1036,7 @@ private function wrap_breadcrumb() { | |||
* | |||
* @return string | |||
*/ | |||
private function get_output_id() { | |||
private static function get_output_id() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't have to be static. See earlier commments
@@ -1012,7 +1024,7 @@ private function wrap_breadcrumb() { | |||
$output = apply_filters( 'wpseo_breadcrumb_output', $output ); | |||
|
|||
if ( WPSEO_Options::get( 'breadcrumbs-prefix' ) !== '' ) { | |||
$output = "\t" . WPSEO_Options::get( 'breadcrumbs-prefix' ) . "\n" . $output; | |||
$output = "\t" . '<span class="breadcrumbs-prefix">' . WPSEO_Options::get( 'breadcrumbs-prefix' ) . "</span>\n" . $output; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain the reason for adding the class
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Give the opportunity to style it. Previously, this was just text thrown in the middle of nowhere, without even a wrapper element.
If this pull is ready for a new round in the process, please ping. So we (I can help you) can add some unit tests |
Addressed first part of the code review. Pending decision on the other points. |
We do not want to burden people who setup Yoast SEO with theme-specific settings. Conclusion:
Also implementing this for the shortcode is the following theoretical way: // Unhook the default Yoast shortcode implementation.
remove_shortcode( 'wpseo_breadcrumb', 'wpseo_shortcode_yoast_breadcrumb' );
function my_prefix_shortcode_yoast_breadcrumb() {
return yoast_breadcrumb( '<nav>', '</nav>', false );
}
add_shortcode( 'wpseo_breadcrumb', 'my_prefix_shortcode_yoast_breadcrumb' ); Suggested KB article alternative, with explanation on why this is better than just a if ( function_exists('yoast_breadcrumb') ) {
yoast_breadcrumb( '<nav id="breadcrumbs" aria-label="You are here:">', '</nav>' );
} Suggested: |
Looking at the PR there are two additions which look to be useful:
As I cannot find any requests about having this breadcrumb-prefix filterable, I don't want to add another filter based on a theoretical situation. If the |
Sure, will do another PR then. Only minor consideration: |
For the example code I don't think we need to make it overly complex and a custom translation system needs to be implemented to make that possible as that string does not appear in WordPress itself. |
Summary
This PR can be summarized in the following changelog entry:
<nav>
element for better SEO, semantics, and accessibility.Relevant technical choices:
Things are a bit complicated in terms of backwards compatibility because the rendered markup depends on parameters e.g. the before / after and the filters. Also, there's the related shortcode to take into consideration.
To keep things simple, I've opted for adding an user option and override the rendered markup. I guess this would need to be discussed, any feedback welcome. I couldn't think of an alternate, reasonable, way to do it.
<nav>
element with anaria-label
attributearia-current
to the active item<span>
to the prefix, as this text was rendered without an easy way to target it with CSSTest instructions
Add the breadcrumbs in the
single
template of your theme, following the example on https://kb.yoast.com/kb/implement-wordpress-seo-breadcrumbs/Add the following quick'n dirty core in your theme's
functions.php
to test the filters for the ID and CSS class:Add the shortcode in one of your posts:
[wpseo_breadcrumb]
<p>
passed as parameter<span>
wrapper has the ID and class added via filtersaria-current
attributeThen, go in Search Appearance > Breadcrumbs and enable the "Use breadcrumbs as navigation" option
<nav>
element<nav>
element has the ID and class added via filtersaria-label="Breadcrumbs"
<span>
wrapper is removedaria-current
attributeNote: also the breadcrumbs in the content added via the shortcode are now within a
<nav>
element. One one hand, users set an option so this would be expected. On the other hand, we can't predict where the shortcode will be placed into the content so there might be edge cases where layout is affected. Any suggestions welcome.As said, with the option enabled the
$before
, $after, and thewpseo_breadcrumb_output_wrapper
filter won't have any effect. I guess this should be documented somewhere.UI changes
Fixes #6728