Making web accessibility sexy

Tom Golden
Tom Golden

The World Wide Web is designed to be as accessible. Using the right HTML tags and attributes will result in a website that is by-and-large friendly to those who do not have the required coordination to use a pointing device (like a mouse or trackpad), as well as usable by those with visual impairment.

It's only when we try to make things pretty rather than functional that we start to make things harder for these users.

Of course, most websites are more interested in the 80-90%[1] of visitors that do not have disabilities. As such, appearance typically takes a higher priority.

This article is not to discourage people from serving the majority. This article is to show a few ways to improve the appearance of your website, while facilitating those with impairments with minimum effort.

Large companies have a lot riding on providing an accessible service, and those ought to put more thought into it than these solutions offer. This article is for everyone else.

Interestingly, there are about double the number of people with involuntary impairments than the number of people who use the largely voluntary impairment that is Internet Explorer.


You know, this thing:



When you navigate a page using the keyboard, with [TAB], [ENTER], [SPACE] and the arrow keys, these glows appear from the currently focused element, so the user can see "where they are", so to speak.

I've worked with plenty of people writing websites who don't know why they're there. And I've worked with plenty more who use the keyboard to browse websites all the time, as it's often faster.

The former group always say the same thing. What is that blue border? How do we get rid of it?

DO NOT GET RID OF THE GLOW ...unless you're replacing it with something else.

And replacing it with something else is no mean feat.

Here's a naive effort:

:focus {
  outline: 0; /* <- disable glow */
  background-color: yellow;


The default browser styles give the element in question an outline, which works well as it is a relatively uncommon selector which is visible for both block and inline elements.

But for more arty projects or design centric companies, these are considered unattractive. And as the vast majority of users don't realise that these outlines have an actual purpose, they will think it's just ugly design.

So the aim is to come up with an alternative that is arguably less ugly, has some element of context to the element it is referring to, and won't clash with other styles. After all, it ought to be easily visible, as that is it's purpose.

(For the record, this article by David Gilbertson gives a JS way of ensuring styles are only visible if you're actually using tabs for navigation:

Previous attempts

Whenever you change the default :focus styles, you may run into problems of another selector with a higher specificity overriding the styles. For instance, if your focused element already has a box shadow from class or id selector styles, then the focus may not appear at all, which would be a big accessibility and usability no-no.

Putting !important on the :focus property values may fix the issue but will probably end up causing others.

Default styles

/* no style declaration */


Browser normalised outline

Most reliable and consistent, but arguably most ugly.

:focus {
  outline: 2px solid #3a99fc;


Browser normalised box-shadow

As ugly as the chrome focus, but consistent cross-browser. Can run into problems with focused elements that already have a box-shadow.

:focus {
  outline: 0;
  box-shadow: 0 0 4px #3a99fc, 0 0 4px #3a99fc, 0 0 4px #3a99fc inset;


Use a background-color

When used with block elements, this can look quite good. But many focusable elements already have a background, which means some TLC is required, and it is probably not worth it for the end result.

:focus {
  outline: 0;
  background-color: rgba(58, 153, 252, .3);


Opaque background-color with 4 box-shadows (highlighter style)

Similar issues as previous, except (1) it looks better, (2) it will at the very least be visible in the majority of cases where either a background or a box-shadow is not already given to the element, and (3) it might be difficult to find an opaque colour that pairs with every possible adjacent colour.

:focus {
  outline: 0;
    -3px -3px 0 rgba(158, 203, 253),
    -3px  3px 0 rgba(158, 203, 253),
     3px -3px 0 rgba(158, 203, 253),
     3px  3px 0 rgba(158, 203, 253);


Translucent pseudo-element overlay

Avoids most of the clashes, and looks great with block elements. Whereas changing the background color of an element might cause non transparent images inside to look awkward, this will overlay them.

Definitely my favourite appearance-wise, and the Google Play Music app which is very tab-key friendly uses it for the play button, next-song button and so on.

Key issues:

  • Reduces contrast, potentially making it a problem for the visually impaired.
  • Clashes with anything with the same (before/after) pseudo element.
  • Does not work for any tags that cannot contain pseudo elements, which is a lot of them, including many form inputs, and img tags.
  • Adding position: relative to an element can have some wild side effects.
:focus {
  position: relative;
  outline: 0;

:focus::before {
  content: '';
  display: block;
  position: absolute;
  z-index: 9999;
  pointer-events: none;
  top: -3px;
  left: -3px;
  right: -3px;
  bottom: -3px;
  background-color: rgba(158, 203, 253, .4);


My current (low-effort) method - filter: drop-shadow

:focus {
  outline: 0;
  -webkit-filter: drop-shadow(0 0 0.2ex);
  filter: drop-shadow(0 0 0.2ex);


It's a shadow. It looks a bit strange, but:

  • It works with block and inline elements, as well as wrapping text
  • The drop shadow has context of the element (the colour of the shadow is the element's color and the size of the shadow is relative to the element's font-size)
  • It rarely clashes with anything as filters are so rarely used on focusable elements.
  • It looks at transparency and border radii to generate the shadow.
  • You can customise how the shadow looks on block elements by changing the block element's color and font-size, which does not affect the block element's appearance itself, and the effects on the descendants can be overridden by the children.


Effect relative to font-size

Unfocused → Focused
Unfocused → Focused
Unfocused → Focused

Effect shares font color

Unfocused → Focused
Unfocused → Focused
Unfocused → Focused

Background and transparency friendly



A more resilient version of the solution would be to test for filter support and then use the native browser as a fallback, and have vendor prefixes.

Reading every word on Wikipedia using Node.js

Making Node do exactly what it wasn't designed for (and do it well)

I'm switching back to Linux

Does this mean I'm part of the PC Master Race?