0

What I mean by dropdown is the implementation found in Bootstrap and other common front-end frameworks. I want to replace <select> elements in my forms with dropdown menus because I need the following features:

  • Better search
  • Dynamic option creation

Both the above can be fitted inside the dropdown menu along with the options. Let's say I have the following markup:

<div class="dropdown">
  <button class="btn" data-toggle="dropdown" type="button" id="dropdown-toggle-btn-1" aria-haspopup="true" aria-expanded="false" data-value="">
     Favorite animal
  </button>
  <div class="dropdown-menu" aria-labelledby="dropdown-toggle-btn-1">
    <a href="#" class="dropdown-item" data-value="cat">Cat</a>
    <a href="#" class="dropdown-item" data-value="dog">Dog</a>
    <a href="#" class="dropdown-item" data-value="elephant">Elephant</a>
  </div>
</div>

When the user clicks on a .dropdown-item, I will use JavaScript to change the string "Favorite Animal" to "Cat", "Dog", or "Elephant" (depending on which one is clicked), and also update the data-value attribute of the toggle with the option's one.

So far, this seems fairly easy to pull off. However, I am worried about accessibility. Is this actually accessible to users? I mean from a visual point of view, it is easy to understand that this is asking users to select an option, but what about from the point of view of screen readers? Any help is greatly appreciated!

13
  • 1
    Firstly what is "better search" as there is no search demonstrated in your example? Are you meaning autocomplete as that is an entirely different pattern. Secondly you can dynamically add <option>s to a <select> (and edit them) so that is no issue with regards to dynamic option creation. Unfortunately the above example is not accessible at all, using <a> for options is one big issue, not using an <ul> for the options (so it announces the number of options) is another. Plus you have to implement all the keyboard functionality yourself which is hard work. – Graham Ritchie Jan 7 at 13:38
  • @GrahamRitchie I decided to not include the search and dynamic option creation because I honestly just wanted to know if this pattern could be made accessible. Do you have any reference to custom select boxes that implement everything I mentioned, but also does so in an accessible way? – darkhorse Jan 7 at 13:49
  • 1
    But the question still remains, are you wanting a combobox (autocomplete) or a select, they are both very different in how you implement them. this article is a good starting point, you will still need to make adjustments such as using an <ul> but it shows the correct aria attributes and explains some considerations such as keyboard controls and expected behaviour. Could you explain further / make it more clear why you can't just use a <select> as you are heading for a lot of work creating your own. – Graham Ritchie Jan 7 at 13:51
  • @GrahamRitchie I am trying to implement something like Select2 (select2.github.io). Except I want to use pure JavaScript, without any jQuery dependency. – darkhorse Jan 7 at 13:55
  • 1
    finally you may want to move this question over to / re-ask this question on stackoverflow.com as it is more about markup / JS, gives you a better chance for an answer! – Graham Ritchie Jan 7 at 14:12
1

Think accessibility first (and mobile second)

Designing and creating web components first and thinking about accessibility afterwards is a common mistake. Adding accessibility afterwards makes it unnecessary difficult. This counts for the very first approach to design (scope and structure), for the visual details (color, clarity and contrast), content (labeling, readability) but also for the implementation (flow and semantics). The latter is the main problem in your example.

The idea is to start making the list accessible for keyboard and screen reader users. After that you can add the visuals needed. This is how your code could change, below is an explanation:

        <div class="label" id="fav-animal-label">Favorite animal</div>
        <div class="dropdown">
            <div class="btn" aria-hidden="true" tabindex="0" data-toggle="dropdown" id="dropdown-toggle-btn-1" data-value="">
                Choose an animal
            </div>
            <fieldset>
                <legend id="fav-animal-legend" class="sr-only" aria-describedby="fav-animal-label">Choose your favorite animal</legend>
                <div class="dropdown-content">
                    <input name="fav-animal" type="radio" id="option-1" value="cat" class="sr-only"><label class="dropdown-item" for="option-1">Cat</label>
                    <input name="fav-animal" type="radio" id="option-2" value="dog" class="sr-only"><label class="dropdown-item" for="option-2">Dog</label>
                    <input name="fav-animal" type="radio" id="option-3" value="elephant" class="sr-only"><label class="dropdown-item" for="option-3">Elephant</label>
                </div>
            </fieldset>
        </div>

Please note that I added the code as an example, it doesn't have to be the definite code.

First I added a label above the dropdown. It is not a semantical label because it is not directly linked to an input field. A dropdown is a control that helps keeping the visual space clean, obviously screen reader users don't benefit from this and you don't have to mimic this behavior for them. That's why I hide the button for screen reader users since all they need is the fieldset which is supported well by most screen readers. No need to make that a semantical <button> too, just add the visuals to make it appeal like one. With tabindex="0" it is still accessible with a keyboard. The options are radio buttons that are put together in a fieldset so that users never loose context. This is assured with a clear text for the legend element. This legend can be visually hidden just like the radio buttons.

To show that and how it works I have created this fiddle with minimal style and javascript.

Note: This is just example code to show how to think about accessibility in the context of the given code example. As said in the comments this code has still some issues and should not be used as is. Please feel free to improve the fiddle and add it in the comments.

When you want to add a search to the dropdown, things get more complicated, but the approach should be the same. And don't forget to test it. Try using my fiddle with NVDA or VoiceOver for example.

5
  • 2
    First part of the answer is great, but please reconsider your HTML example, it is actually worse than the original markup for accessibility. Firstly you have a button that you have attempted to hide with aria-hidden, but it is still in the focus order of the page so that does nothing (you can't use aria-hidden on active elements effectively). The button is not associated with anything anymore, does not show an open or close state as you have removed the relevant aria attributes and as such would be very confusing for a screen reader user. – Graham Ritchie Jan 9 at 15:29
  • 1
    Secondly when in reading mode this will read "Favourite Animal, Button: Choose An Animal, Legend: Choose your favourite Animal, Favourite Animal", as you can imagine that is not a good experience! Trying to design custom components is always difficult because of things like this! – Graham Ritchie Jan 9 at 15:29
  • Additionally when I tab to the button it may actually announce as "blank" as you have attempted to hide it (NVDA announces blank, JAWS just announces it as a button). Also your focus order gets broken as you tab onto the button but then tabbing again takes you into the hidden radio buttons (if they aren't already visible) so you now have two tab stops for a control that should only have one. I think I have made my point and don't mean to come across as an arse, just trying to show why semantic elements are nearly always better and how painful it is developing custom controls! – Graham Ritchie Jan 9 at 15:37
  • 2
    @GrahamRitchie That’s great feedback, thanks! What I tried to do here is modify the example to make some points clear. I didn’t have much time or had the intention to come up with the perfect solution and only tested with VoiceOver. I tried to give keyboard users the opportunity to step into the option list by tabbing but leave the button hidden for screen reader users as they don’t need to open the list. You have definitely a point about how that turns out when using different screen readers. When I find the time I will have another look at this. Btw I totally agree with your last statement. – jazZRo Jan 9 at 16:40
  • 1
    +1 thanks for turning some of the comments into an answer. I feel like when you are thinking accessibility first, it already incorporates device usage. If you think mobile first, it is another way of approaching accessibility by prioritizing device as a context. So in a way I would say that there is not much difference. – Michael Lai Feb 8 at 1:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.