warning: this is my first post (and it’s ended up quite long)
As a front end engineer, accessibility is something that we should consider whenever building a component/feature on a site. It just clicked over this COVID weekend — that I could write an article about it.
The origin story
tl;dr I had to build a simple search component in a narrow space and it didn’t work well with too many results appearing in the drop down. I wanted to find a better solution, so browsed the web for inspiration.
On a recent project, we built a search component — it was nothing special, an input field and a menu that appears like an autocomplete would. It was in a navigation bar so the component had to share space with a logo and links in the navigation. This meant that there was a constrained width of say 380px for the input and the drop down, cool. We didn’t have the content that would go in the search dropdown when it was initially designed. When we did get the content the search results were A MESS. Imagine typing in “search term” and seeing 30 results in a narrow drop down you could scroll through. There’s a reason why Google autocomplete limits its results to 10. It would be too overwhelming to scroll through all the autocomplete items.
tl;dr I enjoy retail therapy — trainers (sneakers) especially. I’ve seen some great uses of search. But oh snap, they sometimes don’t work well in terms of accessibility.
E-commerce sites are a good source of inspiration when looking into search practices — they have a huge catalogue of items that need to be displayed for users. I enjoy a good pair of trainers (“sneakers” for everyone else) so went to size.co.uk. I could see how their search approach could benefit the site I was working on. They display their results full screen in a sort of modal, those 30 results our site was displaying could be reduced and be presented in columns representing the categories the results are from, great.
So with my engineering hat on I thought it wouldn’t take too long to implement, maybe half a day to adjust the currently implemented solution to this modal-esque solution. On click/enter of the search input, open the modal and set the focus to the modal search input, cool cool cool. So I thought about accessibility — then I thought… OK it’s going to take much longer than half a day.
Whats wrong with it? (Part 1)
tl;dr From a keyboard user point of view — it’s a hot mess. And that’s not limited to the search. A sighted keyboard user can’t see what they have selected anywhere on the site.
Accessibility is many things — but my initial focus (sorry) was on keyboard users. Check out what WebAIM say about keyboard users:
A keyboard user typically uses the Tab key to navigate through interactive elements on a web page — links, buttons, fields for inputting text, etc. When an item is tabbed to, it has keyboard “focus” and can be activated or manipulated with the keyboard. A sighted keyboard user must be provided with a visual indicator of the element that currently has keyboard focus. Focus indicators are provided automatically by web browsers.
So, from just testing it out — I noticed as I tabbed, I had no idea where on the site I was. I just wanted to get to trigger the search input in the navigation without clicking on it.
The reason why
There is a global style applied to overwrite the the default focus styles provided by the browser.
This isn’t uncommon. Normally the reason this is applied is because the engineer/designer isn’t aware of the importance of the focus style. A user clicking on a navigation item would see this outline — which often doesn’t look good, so the focus style is removed.
Whats wrong with it? (Part 2)
tl;dr We’ve reinstated the browser default focus styles by removing that global selector
:focus . But now the keyboard navigation isn’t intuitive and doesn’t match the visual layout.
I mentioned earlier that accessibility is many things. My initial focus (sorry again) was on keyboard users. Specifically sighted keyboard users. When someone is tabbing across the site they should expect to move across it in a linear fashion. E.g. I’m here, when I push tab I should be here + 1 (here to the right of it). Check out what WebAIM say about navigation order:
As a keyboard user navigates through the page, the order in which interactive items receive keyboard focus is important. The default keyboard navigation order must be logical and intuitive. This generally means that it follows the visual flow of the page — left to right, top to bottom. For most pages this means header first, then main navigation, then page navigation (if present), and finally the footer. This navigation order (and also the reading order for screen readers) is determined by the web page’s source code.
So, the outline has been restored and I’ve exaggerated it so it’s easier to see, we’ve just landed on the page — let’s begin hitting that tab button to get to search:
So we can see how this could be confusing for a keyboard user. I’ve actually found it impossible to get into the search dialog/modal with a keyboard (please let me know if you can). So, let’s continue this journey/experience — let’s say I could access the search with a keyboard.
Whats wrong with it? (Part 3)
tl;dr The search is open now — But I can’t get out of it.
So, I was saying that I couldn’t get out of this interface. And i’m talking as a keyboard user. If I were using a mouse — sure I could click on that close button on the top right and I’m back on the page. But in this case, I’m not using a mouse. I’ve called this interface a modal/overlay/lightbox — it’s a UI that’s on top of another UI. What does w3.org suggest about modals?
Escape Closes the dialog.
So that’s a good recommendation — as I’m in this new state I can hit the escape key to get out of it. Unfortunately this wasn’t implemented. But I did mention that close button they provide. So all I need to do is tab to it!
So I can’t navigate to it with the keyboard, why is that?
The close “button” element is a
<div>. The browser doesn’t see it as an element it needs to give a tabindex to. So by default it can’t be tabbed to.
We could fix this by giving it a tab index:
tabindex="0" , or letting the browser make it tabbable with
role="button" or using an actual
<button> element instead of a
I’m not finished with this button. I thought I’d mention some other accessibility issues — such as how Colour contrast could be an issue. And as it’s using a pseudo element to display an icon — a user with a screen reader wouldn’t be able to read out any text, to give the user some context about what it does.
Whats wrong with it? (Part 4)
tl;dr The focus was set on the input field when this UI opened, what happens if I keep hitting tab? We’ll end up outside the search modal/UI and be able to select content we can’t see.
So, I’ve entered a search term and I’ve found some results — now this is an edge case here, so please bear with me. As a user I could tab from the search input field down to a result — decide it’s not for me and continue tabbing to the “Recently viewed” section, what should happen when I get to the last item?
What actually happens, the user can continue to tab — with no visual indicator of where they are:
What’s happening here? If I lower the opacity of the search overlay/modal we can see what’s up.
We can see what’s happening now — after the last element in the search overlay, we’re tabbing to the next item in the DOM which is outside the overlay. If we continue to tab we’ll go through the entire site while it’s hidden behind the overlay.
What should happen? Ideally when the user gets to the end of the items in the search component/widget/UI:
- The search widget closes and the user is back on the main page.
- Or the focus goes back to the start of the search component, to the input field.
Point 2 is a common practice — A focus trap is when you override default user input so that the user is kept tabbing within the modal. By adding an event listener, listening for keyup events and working out whether the event.target is in the search container, if it’s not you can assume they’ve tabbed out — so you set the focus to the first element or a close button.
What’s my point?
tl;dr It’s going to take longer than half a day to build a fully working search component.
Building out a component can be a simple and a short task. But sometimes you can take a step back and think about accessibility before you begin implementing a solution. Like I said, this is just one consideration around accessibility — we could go through a site with a screenreader like VoiceOver and find issues.
I didn’t intend to tear this site apart and it’s likely I could go to many sites that have a search similar to this and find issue. This was just the rabbit hole I went down looking for a different search implementation.