The quantity selector question
Tags that this post has been filed under.
Last week while talking to one of my colleagues they asked me: How do you call this component?
It's comprised of a plus and minus button and a number indicator. Typically used to increase or decrease a quantity by a predetermined factor: one, four, ten, 100K, etc.
My first thought was: off course, a "quantity selector".
I have seen this so many times. It can be found in Product Detail Pages (PDP) or Shopping Carts, allowing users to change the quantity of selected items with one easy click.
These selectors sometimes are designed and implemented differently. For instance some websites like to use up and down arrow on top of the selector, some rather use a dropdown while others provide an input box.
Instead of answers, I had questions:
- Is there a design pattern recommended for this component?
- Why do we have multiple representations of this component?
- Are there any benefits of having a dropdown vs an input box vs a quantity selector?
role="spinbutton"
To provide accessible solutions, I always refer to WAIA-ARIA Practices when looking for ways to implement a new component or any element I have doubts with.
Luckily ARIA Practices has a pattern that resembles the interaction required by this component. Let me introduce you to: role="spinbutton".
A spinbutton is an input widget that restricts its value to a set or range of discrete values.Spinbuttons often have three components, including an
<input>
text field that displays the current value, an increase and a decrease<button>
.
Playground
Let's build our component and detail the interaction and visual requirements. Use the following element as your interactive demo.
<div role="group" aria-labelledby="qtySelectorLabel">
<label id="qtySelectorLabel">Select Quantity:</label>
<div class="grid">
<button type="button" tabindex="-1" aria-label="decrease quantity" class="decrease"><span class="aria-hidden">-</span></button>
<input type="number" value="1" min="1" max="10" step="1">
<button type="button" tabindex="-1" aria-label="increase quantity" class="increase"><span class="aria-hidden">+</span></button>
</div>
</div>
Input selector
I like to use <input>
element of type="number" as they include built-in validation to reject non-numerical entries and also provides the attributes min and max to constrain the possible input values. A JavaScript validation is recommended though, as min / max are only validated on form submit.
Another important attribute is step: a number that specifies the granularity that the value must adhere to. For example to increment by four units you can use <input step="4">
Lastly, for mobile devices, this input brings a numeric keyboard. Reducing the amount of interaction one must make with the element.
Please read why the GOV.UK Design System team changed the input type for numbers, there are some important inconsistencies in Screen Readers & dictation applications while using this input element.
When using <input type="number">
the browser may opt to provide stepper arrows to let the user increase and decrease the value using their mouse or by tapping with a fingertip (although target are is really small).
To remove them use the following CSS code:
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
-moz-appearance: textfield;
margin: 0;
}
Buttons
Because we are using editable field, it's recommend to make the text field as the only focusable element. The buttons should accessible via any pointer device & the arrow keys. This will prevent the field from having three focus stops.
We'll use tabindex="-1" on the buttons to prevent them from being focused via keyboard.
To give each button an accessible name aria-label will be used. Lastly the content inside the buttons will be hidden to Screen Readers using aria-hidden, as they could be icons and they don't add proper context to the component unless properly labelled.
Keyboard interaction
The following pattern is recommended by WAIA-ARIA Practices' design pattern while interacting with this component:
- Down arrow : should decrease the value by 1 step.
- Up arrow : should increase the value by 1 step.
- Page Down : Decreases the value by 5 steps.
- Page Up : Increases the value by 5 steps.
- Home : Decreases to minimum value.
- End : Increases to maximum value.
Disclousure: I have never seen Page Up / Page Down implemented before. This should be validated by data of usage. The team should also determine the value for each step increase/decrement as it could depend on the selected category. For instance, in a previous client tires and rims quantity selector was incremented by four, where as any other product was incremented by one.
ARIA
No ARIA is better than bad ARIA.
It is important to consider how to make your components accessible for Screen Readers. Let's try do a good job and learn what's required for this component.
- role="group": The group provides a means to inform assistive technology users that the buttons are related to the single purpose of choosing a value.
- aria-labelledby: A hidden label that provides the accessible name for the group. "Choose quantity".
- aria-label: Defines the accessible name for each spin button ("increase", "decrease").
- aria-hidden: Hides button content from Screen Readers.
Important: if a non-semantic element (e.g <div>
) is used to display the value of the widget, the following ARIA attributes must be set: aria-valuenow, aria-valuemin, aria-valuemax. When using <input>
these are provided by value, min, max attributes.
Interaction Cost
The steeper design pattern works great to reduce the interaction cost. To change the value of the field only 1 interaction is needed: click, tap or arrow key. But then why so many eCommerce sites use dropdown as a Quantity Selector?
A dropdown requires several gestures: select the field, scroll and select value, hit done.
It wasn't until I read Design Guidelines for Input Steppers by Neilsen Norman Group that I understood why.
"The interaction cost of the stepper would be much higher if the user wanted to increase the number from 1 to 10; this increased cost for large deviations from default is a major disadvantage of using steppers."
"When users need to change a value from 1 to 50, an input stepper is not a wise choice. Steppers make sense for numerical parameters with a clear default that most users are likely to select."
End notes
Curiosity is the key to creativity. Is essential to human nature.
What started as a conversation with my colleagues, lead to the research and ended up in the writing of this article.
The think I love more about learning, is sharing what I know.