Opened 4 weeks ago
Last modified 21 hours ago
#63581 new defect (bug)
paginate_links: The current page should be an a element, not a span element
Reported by: |
|
Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | |
Component: | General | Keywords: | 2nd-opinion has-patch |
Focuses: | accessibility | Cc: |
Description
Originally reported at GB 70439
The paginate_links
function outputs the current page as a span element. Example:
echo ( array( 'current' => 1, 'total' => 10 ) ); <span aria-current="page" class="page-numbers current">1</span> <a class="page-numbers" href="">2</a> <a class="page-numbers" href="">3</a> <span class="page-numbers dots">…</span> <a class="page-numbers" href="">10</a> <a class="next page-numbers" href="">Next »</a>
However, this may cause an accessibility problem for screen reader users, as the current page is not focusable.
Ideally, the HTML markup should be:
<a aria-current="page" class="page-numbers current" href="">1</a> <a class="page-numbers" href="">2</a> <a class="page-numbers" href="">3</a> <span class="page-numbers dots">…</span> <a class="page-numbers" href="">10</a> <a class="next page-numbers" href="">Next »</a>
However, this change will impact many themes that include a span element as part of their CSS selectors.
I would like to clarify whether the current HTML really has problems from the viewpoint of accessibility in the first place. I look forward to feedback from people who are knowledgeable about accessibility.
Change History (7)
#2
@
3 weeks ago
In my opinion, the linked approach seems to be a better approach as the same is used in the recommended markup structure at https://design-system.w3.org/components/pagination.html
The original issue description mentions the same
However, changing the current markup would also cause issues with existing themes that expect current page to use the <span>
tag...
#3
@
3 weeks ago
I've analyzed the paginate_links()
function in https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/general-template.php#L4627-4807 and would like to propose a backwards-compatible solution.
Current Issue
The current page is output as a <span>
element:
<?php $page_links[] = sprintf( '<span aria-current="%s" class="page-numbers current">%s</span>', esc_attr( $args['aria_current'] ), $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] );
This creates accessibility issues as screen reader users cannot focus on the current page indicator.
Proposed Solution
Add a new link_current parameter to the $defaults array with backwards compatibility:
<?php $defaults = array( // ...existing parameters... 'link_current' => false, // NEW: Whether to link the current page for better accessibility );
Then update the current page logic to conditionally create a link:
<?php if ( $n === $current ) : if ( $args['link_current'] ) { // Generate current page URL (same as current page) $current_link = str_replace( '%_%', 1 === $n ? '' : $args['format'], $args['base'] ); $current_link = str_replace( '%#%', $n, $current_link ); if ( $add_args ) { $current_link = add_query_arg( $add_args, $current_link ); } $current_link .= $args['add_fragment']; $page_links[] = sprintf( '<a aria-current="%s" class="page-numbers current" href="%s">%s</a>', esc_attr( $args['aria_current'] ), esc_url( apply_filters( 'paginate_links', $current_link ) ), $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] ); } else { // Keep existing span behavior as default (backwards compatibility) $page_links[] = sprintf( '<span aria-current="%s" class="page-numbers current">%s</span>', esc_attr( $args['aria_current'] ), $args['before_page_number'] . number_format_i18n( $n ) . $args['after_page_number'] ); } $dots = true;
This ticket was mentioned in PR #9088 on WordPress/wordpress-develop by @iamadisingh.
3 weeks ago
#4
- Keywords has-patch added
Trac ticket: https://core.trac.wordpress.org/ticket/63581
Summary
Adds a new link_current
parameter to the paginate_links()
function to improve accessibility by allowing the current page to be output as a focusable link element instead of a span.
Problem
The current implementation of paginate_links()
outputs the current page as a <span>
element, which creates accessibility issues for screen reader users as the current page indicator is not focusable. This makes it difficult for users navigating with keyboards or assistive technologies to interact with the current page element.
Current behavior:
<span aria-current="page" class="page-numbers current">2</span>
Desired behavior:
<a aria-current="page" class="page-numbers current" href="...">2</a>
This ticket was mentioned in Slack in #accessibility by joedolson. View the logs.
31 hours ago
#6
@
31 hours ago
Screen readers will announce aria-current
on a list item, it's just that you have to be reading the text, rather than navigating by tab. I question whether there's any benefit to a user to add the current page into the tab list.
From a screen reader user standpoint, you navigate in reading mode if you want to discover information; and you're more likely to navigate by tab if you're specifically looking for an action to take. The current page is information, but it's very unlikely to be an action the user wants to take.
If the pagination output was always consistent, containing the same links in all cases, then I'd think that having this present would be more important; but the pagination links change in every view, so they are never totally consistent.
I think that adding a parameter that would support having this linked is fine; but I'm not convinced this is a problem that needs to be solved. Increasing the complexity by making this an additional option seems to have a pretty marginal benefit.
The W3C Pagination and Breadcrumbs pages follow one of Scott O'Hara's breadcrumb pattern examples. Scott's third example assigns
aria-current
to theli
element, without a link, and the usage notes present arguments both for and against linking.Changing the function's default behavior now would require a clear and significant improvement. I do not think the linked pattern is much better, but others might disagree.
However, choosing to link the current page probably could be easier. I only know one way to alter the markup: using
preg_replace()
within thepaginate_links_output
filter.