That is, a button that can be tabbed to, accessible to screen readers and also not implying a semantic link to another document
Yes, and curiously enough it's called just that: <button>
. Or <input type="button">
if you only need text content. You can then add a load of CSS to it to stop it looking like a default form button if you prefer.
The one problem is IE, which adds an extra couple of pixels of unremovable padding to button widgets, and moves the content of the button down and to the right one pixel when clicked. Often this doesn't matter. If you don't need zero padding you could also compensate by adding padding on all browsers except IE.
Another semantically sound possibility is to use an <input type="image">
, although that obviously requires the content to be an image. Relying on the alt text instead doesn't work due to IE's rendering of broken image icons.
Whilst buttons are semantically by far the most appropriate element, if you don't want this styling trouble you can continue to use a span or other meaningless element (like SO does), but at least improve the keyboard accessibility by giving it a tabindex
value. It will then be focusable like a link, though unfortunately you need extra scripting if you want to make it activatable from keyboard (catch at least keypress codes 13 and 32). You can also label such an element as a button with ARIA for accessibility, athough to be honest I'm not convinced this really does anything much useful for today's toolset.
Sometimes when the action is related to another element on the page, such as with the suggested ‘open/hide’ button, it seems legitimate to me to use an internal link to that element. (With a JS-assigned onclick
though, not any of that inline JS or horrific javascript:
pseudo-URLs.)
.hidden { display: none; }
<a href="#foo" class="toggler">open/hide</a>
<div id="foo"> blah </div>
for (var i= document.links.length; i-->0;)
if (document.links[i].className==='toggler')
document.links[i].onclick= toggle;
function toggle() {
var el= document.getElementById(this.hash.substring(1));
el.className= el.className==='hidden'? 'hidden' : '';
}
or similar idiom in your library of choice. This will do something useful in non-JavaScript browsers; you can also add a rule to check the current location's hash, so that if someone opens your show-link in a new tab that document will be showing the element in question.