views:

157

answers:

4

Most of my development life, I have done a JavaScript generated button like so:

<span>Open/hide</span>

With CSS like

span {
    cursor: pointer;
}

This seemed to work for me, and IMO, it looks and seems better than

<a href="(#|javascript:void(0);|javascript:;|return false)">open/hide</a>

However, I'm starting to think people might use links because they are better accessible to screen readers. It also makes sense that the browser will allow you to tab to a link - but not necessarily a span with a CSS style (like my previous example).

Is there a way to get the best of both worlds? That is, a button that can be tabbed to, accessible to screen readers and also not implying a semantic link to another document, and not having to use hacky ways to stop the link from going anywhere?

Note: These are for JS inserted buttons only, not existing links of which their behavior is changed with JS.

A: 

It seems doing

<span tabIndex="n">foo</span>

allows you to tab it. However, pressing enter while it's focused doesn't simulate clicking it. Which I guess is easily remedied by putting a keydown event on it as well.

Tinister
Is the tabIndex attribute proprietary or part of the spec?
alex
It is for HTML 4: http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex though it's not specified for `<span>` tags. However, IE7, Firefox, and Chrome (Webkit) allow you to do it.
Tinister
A: 

I would say that the button fits your requirements ...

<input type="button" class="js_button" value="Javascript Button" />

CSS:

.js_button, .js_button:active, js_button:focus {
    background-color: #FFF;
    border: none;
    margin: 0 0;
    padding: 0 0;
}

Buttons can be tabbed to, are semantic, automatically have tab indexes and keypress actions, and do not imply links to other documents. The only difficulty is removing the mousedown animation -- I'll look around and see if there's anything out there for removing that animation without hacks.

Sean Vieira
A: 

You can link to any object in the page if you provide the id or the name of the element.

For example:

http://stackoverflow.com/questions/1659137/html-elements-for-javascript-hooks#comments-1659137

http://stackoverflow.com/questions/1659137/html-elements-for-javascript-hooks#comments-1659137

voyager
+6  A: 

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.

bobince
Great answer, I do feel a little stupid for not mentioning I knew about buttons, but for some reason assumed that they were a no-go outside of the form element.
alex