1366Days

1366 days since this post was last revised. Specific details are likely out of date.

I’ve never given accessibility as much consideration as I should have. I’ve always done the obvious things like using the correct element where possible but I’ve never gone the whole AAA WCAG 2.0 (Web Content Accessibility guidelines) thing.

Of late I’ve been on a merciless hunt to mitigate mouse use in my day to day work (started with my quarter of the year using Vim and has snowballed from there) and I’ve therefore inadvertently seen how more and more sites fall down when it comes to keyboard navigation. Single page application sites are, generally, particularly poor in this regard.

Of course HTML and UAs have had the basics covered from the off. It’s only web authors like myself that add outline: none to a and button tags and screw everything up. The usual reason is aesthetics. I don’t know any designer that hasn’t wanted to ‘get rid of that ugly outline when I click on the button’. But, when it comes to tab focusable content, that’s very naughty: http://www.w3.org/TR/2008/REC-WCAG20–20081211/#navigation-mechanisms-focus-visible.

I wanted to know if it was possible to get the best of both worlds. An outline if users are navigating by keyboard (and the element gets tab focused) but no outline if the user is clicking/touching.

I’m not saying this is the answer, but I’d really welcome anyone explaining why any part of what I’m doing right now is wrong for accessibility (or otherwise) reasons. Or if there is a better/simpler way to achieve this goal.

Take a look at the demo page and tab through the links. Then try clicking on the links too to see the two possible outcomes.

Or a Codepen if you would rather:

See the Pen Accessible (yet vain) buttons and links by Ben Frain (@benfrain) on CodePen.

It’s a really simple page but we do (at this point) need all three of the web tripartite: HTML, CSS and JavaScript (my JS skills are primitive, there’s no doubt a better way to do it) for this to work:

<button>Click Me</button>
<button>No, Click Me</button>
<button>Or, Click Me</button>

Good ol’ fashioned buttons. Nothing unusual here. Next the CSS:

button {
  outline: 1px solid transparent;
  border: 1px solid #ccc;
  background-color: #ddd;
  padding: .3em .6em;
  -webkit-transition: outline .5s;
          transition: outline .5s;
}

button:focus {
  outline: 1px solid red;
}

button:active {
  outline: none;
}

button.tapped {
  -webkit-transition: outline .35s;
          transition: outline .35s;
  outline: 10px solid transparent;
}

I’m adding a transition to the outline of the button element. This smoothes the transition to the orange border (or whatever colour you like) and also allows our (admittedly grandly titled) ‘shockwave’.

When the element gets focus we show the outline. When the element is active (clicked/tapped) it gets no outline. However as soon as the mouse/finger comes up the element is not active but is still focused. Which leaves me with a border I don’t want. This is because:

These pseudo-classes are not mutually exclusive. An element may match several pseudo-classes at the same time

Read all about it here: http://www.w3.org/TR/css3-selectors/#the-user-action-pseudo-classes-hover-act

There is no CSS :blur pseudo element either so to take away that outline when a user clicks/taps, a little JS:


// Wait for DOM ready
document.addEventListener('DOMContentLoaded', function() {
    var className = 'tapped';
    function adder(clicker) {
        this.classList.add('tapped');
    }
    function remover(clicker) {
        this.classList.remove('tapped');
    }
    var button = document.querySelectorAll('button');
    for (var i = 0; i < button.length; i++) {
        button[i].addEventListener('click', adder);
        button[i].addEventListener('blur', remover);
    }
});

When the user clicks/taps a button, the button gets an additional class (‘tapped’ in this instance). This allows us to remove the outline. It also allows us to do something a little more informative. I wanted to make it clear to the user that they had ‘actioned’ the button. By transitioning to the 10px solid outline I get quite a nice visual effect (in my mind at least). When a user uses the keyboard they get the orange border (nice and clear). When a user is using a different input device (e.g. mouse, finger), they get a very subtle effect.

Summary

This is just riffing, I’m sure there must be a better way to handle this scenario so I’ll be keen to hear how everyone else has tackled the issue of allowing tabbed keyboard navigation AND vain aesthetics to satisfy the needs of designers?

Edit: Just found a post from a couple of years back and the author (Steve Faulkner) essentially came to the same basic idea.

Ben Frain Developer, Author: 'Enduring CSS', 'Responsive Web Design with HTML5 & CSS3'.