Strategies for accessible date pickers

This post is based on my research on proper markup and accessibility for date pickers, related to work on the WordPress Gutenberg project and has been adapted to a more broad audience.

A lot of the literature I could find online, as well as the free programming libraries and examples use outdated version of the WAI-ARIA Best Practices document, the newest version of which does not even mention date pickers.

So here I am, doing research — and I hope it will be useful for others as well.

To boil things down

  1. Do not make the user depend on using a date picker as a primary input method. Instead, use form input fields, with the date filter as an alternative. Provide live validation if the user is limited to certain dates.
  2. If the date picker does not provide functionality other than selecting a valid date, hide it from the screenreader context and tab index.
  3. If the date picker provides additional functionality, an alternative should be provided. Bonus points if the date picker can be the alternative instead.

Providing live validation

Using a JavaScript library such as Moment.js, one can check for a valid date and time as the user enters data into one of the input field you provide using the change event for each relevant input field.

The aria-invalid attribute set to true should be provided to indicate which input field has the invalid date. Once the input is valid again, the attribute is changed to false or removed.

One may also want to provide a validation message with role="status". This indicates to assistive devices such as screenreaders that the message is a “live area” and any updates are provided to the user as soon as the user is determined not to be busy.

Example 1

<form id="booking_form" aria-controls="booking_validation_message">
  <label>
    Date:
    <input id="booking_date" type="text" value="December 25 2018" aria-invalid="true" />
  </label>
  <p id="booking_validation_message" class="invalid" role="status">
    Sorry, we don't fly to London–Heathrow on the specified date.
  </p>
</form>

 
In the case of multiple fields, one should either indicate the specific attribute if possible. When it can’t de determined which field is invalid, the aria-invalid attribute shuld be assigned to the relevant fieldset or the whole form.

Example 2

<form id="booking_form" aria-controls="booking_validation_message">
  <label>
    <input type="text" name="destination" value="London LHR" />
  </label>
  <fieldset id="date_fields" aria-invalid="true">
    <label>
      Day
      <input type="number" name="day" value="31" />
    </label>
    <label>
      Month
      <select name="month">
        <option value="1">January</option>
        <option value="2" selected="true">February</option>
        …
      </select>
    </label>
    <label>
      Year
      <input type="number" name="year" value="2018" />
    </label>
  </fieldset>
  <p id="booking_validation_message" class="invalid" role="status">
    The date provided is invalid.
  </p>
</form>

Hiding from the screenreader context and tab index

The datepicker itself may be hidden away from the screenreader context and tab index by using the aria-hidden attribute and setting the tabindex attribute to a negative number like "-1".

This means that most navigation issues related to the date picker, like treading through the calendar or finding the next or previous month are simply averted by setting it a side, and only depending on the primary input methods.

Example 3

In this example, JSX-like abstraction is used, so we can concentrate on the <div> element, which contents are hidden away from.

<DateForm />
  <div id="datepicker_popover" tabindex="-1" aria-hidden="true" />
  <DatePicker />
</div>

Providing an alternative

In cases where the date picker provides added value like displaying the lowest price for a flight leg over a range of days or indicates the availability of your hairdresser at glance, I highly enoucrage the use of alternatives to a date picker.

A section using the aria-describedby attribute may be used for a textual summary, while one using aria-details may be use for finer details.

But still — sometimes accessibility issues are more closely related to human communications than to markup and techincal guidelines:

  • A beach resort is fully booked during certain days. Is there a way to communicate that more clearly than inside the datepicker?
  • Are there other ways to indicate the lowest fares for a given date range, then to display them in the datepicker itself?
  • Your hairdresser is on vacation over a couple of weeks, and it is displayed in the date picker as a series of disabled dates. How can your hairdresser communicate this differently?

6 thoughts on “Strategies for accessible date pickers

  1. Nice write up! I wasn’t aware of the possibility of live validation using `aria-invalid`. That’s quite useful.
    Airbnb’s react-dates uses a datepicker that is visible to screen readers and provides descriptions to screen readers as a user tabs or arrows over each cell in the calendar.
    http://airbnb.io/react-dates/?selectedKind=DayPickerRangeController&selectedStory=default&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybook%2Factions%2Factions-panel
    Have you checked it out? I think what you are saying about hiding the datepicker from screen readers makes sense, but this implementation seems to make it work.

    Liked by 1 person

    1. My idea about skipping date pickers from the screenreader context and even the tab index stems from my point of view that even if one was following accessibility guidelines by the book, navigating a calendar-based date picker can be an awkward experience for those who are visually impaired.

      Liked by 1 person

      1. Unfortunately selecting dates via text input or set of select-fields is also an awkward experience. It lacks the context of weekdays, adjacent holidays, and other states that a calendar provides.

        I think the UI design problem could be restated as a choice between a “Date-Specifier” and a “Date-Chooser”. In a “Date-Specifier” the user is simply inputting a date that is pretty obvious and context-insensitive – whereas a “Date-Chooser” is all about context, adjacent days, day-states, etc.

        In one case input-fields are ideal for blind users (and even sufficient for *all* users) while in the other some sort of a calendar (or some similarly information-rich, menu-like interface) is far more usable – despite the minor(?) navigation hassle.

        Like

      2. An example use case for a Date-Specifier would be “Your Birthday”, “Your Already Booked Departure Date” – where the date is already fixed and known by the user.

        Regarding “Date-Choosers” the date selection can in *some cases* be split into a simple two-step process where the user selects a rough period (“Early July”, “Late July”, “Early August”, etc.) to get a short list (not a calendar!) of options around their selected period.

        Also, with date-range selections, a combo of “Start-date” and “Length in days” is often (not always, though) easier for users to grok and interact with than a set of two calendars.

        Like

  2. It would be valuable if you provided examples of how fully-booked, lowest fares and hairdresser vacations could be better communicated than inline in the datepicker.
    Also, what do you mean by “Bonus points if the date picker can be the alternative instead”? Could you clarify or give an example?

    Liked by 1 person

    1. This post was split from a more comprehenisve draft that I had written a couple of days ago.

      I intend to visit those questions myself in the coming week or two, but those are intended to be open questions that everyone would be able to appropriate to their own work.

      The idea of using the date picker as an “alternative” was based on my idea that an interactive date picker may be useful to visualise things at glance or to pick a date for a non-impaired user, the main focus should be on something like a set of form input fields.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.