The Actual Buttons Are Actual section of this ​article sums it up nicely why.

Unless the accessibility team have indicated otherwise, each of the 74+ occurrences (only counting PHP files, more in JS files) of links with href="#" should probably be a <button>, so that screen readers interpret it as a button that does something, rather than a link that takes you somewhere. It also reduces the number of links that can be pulled out of context.

Appearance isn't a problem either - taking the "See 3 more…" from the screenshot:

Change History (52)

Agreed - if it behaves like a button, it should be a button. Speaking from the Accessibility team, this is a good suggestion. I'd recommend that this get broken up into discrete tickets, referencing buttons based on functionality/component or file, so that it's easier to handle, however -- as is, this is likely to end up as a mega ticket that nobody has the scope to handle...

each of the 74+ occurrences (only counting PHP files, more in JS files) of links with href="#" should probably be a <button>

Just to point out there are also links with a URL fragment, e.g.:<a href="#post_status" class="save-post-status hide-if-no-js button">OK</a>
which aren't used to point to a target within the current document but they're used as buttons so when searching for occurrences we should search for any link that *starts* with #. At the time of writing (revision 30292), I get 105 occurrences only counting PHP files in /wp-admin/

Divs, spans that behave like buttons should be buttons for sure but thinking about links, as I see it we have two different cases:

links that should be buttons and already look like buttons

links that should be buttons but current design choices want to look like links

Ideally, we should serve all users the same content and just change them in buttons, for example:

Or, to keep the current visual, add to the second ones an ARIA role="button". Visually, they will look like links but their semantics would be "button". Worth nothing screen readers won't list them as links and they will announce them as (based on the example below):

Cancel button

BTW this would work just for screen reader users. We would end up serving content with different semantics to different users. Not sure this is a good thing, fair way to say I'm pretty convinced it would be bad.

A third way could be trying to "fake" buttons with CSS to make them look like links, trying to rebuild hover/focus states. I'm not a big fan of this and not even sure it can be done.

Any thoughts and feedback more than welcome, especially from UI and design people. The functional part is clear, we need UI feedback :)

Could be a link when JS not available, should be a button the rest of the time.

Anchors with meaningful off-page HREF values that are *not* renderable

Should always be a button, but perhaps the target should be made renderable

Buttons that direct to new locations on the same page

Could be either a button or a link.

Buttons that direct to new locations on different pages.

Should be a link.

With the 'either/or' cases, each button or link will need individual consideration, depending on the context of the control. If it could be an anchor, but is in the middle of a whole bunch of buttons, then it would probably be better UX to leave it as a button, for example.

For HTML, we'll be using the classes .button-link for buttons that should look like links.

To organize the work, we'll be creating new tickets. Each new ticket will pertain to a specific file that displays buttons or links that need to be changed. When creating patches, be sure to address both the file that displays the button or link and any JS files that manage the behavior of the control.

Name tickets with something consistent and meaningful, such as the file name and location of the file being worked on.

We can probably have both and show the link/hide the button when no-js.

For example, the "row actions" links, where Approve/Unapprove, Spam, Trash, Reply, Quick Edit, behave like buttons when JS is on. Only the "Edit" link always behaves as a real link regardless of JS support.

Could be a link when JS not available, should be a button the rest of the time.

While that's technically possible, we couldn't find a clean, solid solution. Consider for example the "row actions" links (e.g. in the posts or comments listings). Except "Edit" (which is always a link), with no JS these links are fully functional and semantic, for example:

href="comment.php?c=5&action=trashcomment&_wpnonce=d635621ec8"

so, when no JS, that's a link with GET parameters and it just works. BTW, when JS is on, it acts like a button and uses an AJAX POST.

they should have been built as submit buttons using POST in the first place... unless there's a specific reason to use GET. But refactoring all the admin is out of question.

we could double the markup and serve links + buttons then hide the links when JS is on and hide the buttons when JS is off. But it would end up with ugly markup and ugly PHP.

we could transform the links into buttons with JS. A rabbit hole, especially about events: will break any directly attached events.

The only "clean" solution we could think of is to add via JS role=button on the links. This would help just users who use software that understand ARIA. For all other users, the semantic value of those links would still be "link".
Any thoughts more than welcome.

I think that's a reasonable case for using role=button; the role exists for scenarios where it's an undue burden to convert to a real button, and this seems like exactly that case. Using role=button is something we can always keep an eye on in the future as a candidate for a later revision, if we feel it's necessary.

We should make sure to do testing with AT so that the AT interaction behaves as expected with the button role. We don't want this to report as a button but require activation as a link.

Accessibility: Add an ARIA role button to links that behave like buttons when JavaScript is on.

Introduces a simple way to give a proper semantics of button to links that behave
like UI controls when JavaScript is on and behave like actual links when JavaScript
is off. First implementation on the Terms list table.

If we're going to add role=button, then we should also make sure that any relevant link can be activated by the spacebar, so that it behaves more like a button. Attached patch lets any link with the class 'aria-button-if-js' be activated using the spacebar.

@joedolson not 100% sure about this, it seems to me we should consider 2 different cases:

Screen reader users
Screen readers understand role=button and they activate the control when using Spacebar. An example of this are the "Quick Edit" and "Delete" links in the Categories and Tags screens. When not using a screen reader, Spacebar doesn't work. When using a screen reader, Spacebar magically works. No need for any JavaScript.

Keyboard users (no AT)
They are not informed about role=button. Visually, they see a link. It is unlikely they're going to press Spacebar because the link looks like a link. By the way, it gets a bit more complicated because sometimes links are styled like buttons :) Probably we should make Spacebar work just in this case because what users "see" is a button and users will likely expect it behaves like a button.

Worth considering it's even more complicated than this because there are also low-vision users who use screen readers as an aid in their navigation. They will "see" links that look like links being announced as "buttons". Unrelated to your proposed patch actually, this already happens because of the class aria-button-if-js.

I think that anytime we add an aria attribute that describes something as a button, it *must* be possible to operate it as a button. The fact that some users are unlikely to do so, because they're unaware it can be done, isn't going to have any impact. They'll still be able to activate it using enter.

Honestly, I'd rather that all our buttons looked like buttons; but if we're trying to minimize impact on the design of the admin, I can live with that.

Do all screen readers now add the space bar as a keyboard control for role=button?

I think that anytime we add an aria attribute that describes something as a button, it *must* be possible to operate it as a button.

It is possible already, for technologies that understand ARIA. My concern here is while ARIA works only for assistive technologies users, that JavaScript bit will work for all users and basically it will alter the standard interaction with links for users that don't use AT.

I don't think it will harm the user experience to have an additional option for using these link/buttons; and if somebody is using a future technology that reports ARIA information to them visually, it could be important in the future.

But I'm also uncomfortable with the idea of offering a different user interaction depending on what technology people use that isn't fundamental to their technology. I can easily imagine a scenario where a screen reader user is trying to instruct somebody on a task in WordPress, and they keep saying "tap the spacebar to quick edit", because that's how it works for them.

I don't like the "sort of a button" interaction model, regardless of the design of the element.