Maybe You Don’t Need a Date Picker

Calendar controls, date pickers, date widgets, whatever you call them, however they are described, they follow the same basic principle — present the user with a calendar to enter a date (and sometimes a time).

The native implementations come from browsers when authors use <input type="date">. Usually a calendar grid, but sometimes built to look like a broken slot-machine or configurable date rubber stamp that your accountant uses.

Frameworks and libraries offer their own take on date pickers, with many more options from third-party developers. These appeal to developers who want control over the visual style, and sometimes function, of the date picker. Particularly developers who want to avoid a different experience across browsers.

The problem is that nearly every implementation of a date picker is a barrier for some set of users. I can comfortably say every one that I have seen is a problem, though perhaps there is a wonderfully robust one somewhere. Even the ARIA Authoring Practices, which is more comfortable with imperfect patterns, has not deigned to create a date picker.

8 February 2024. LOL, of course APG added a date picker, and of course it uses an attribute with no browser support, and of course it left it in there anyway 4 years ago justifying that decision with hope. APG continues to be full of anti-patterns.

Challenges

I have been testing with users for about 20 years (so far). Something I see over and over again is the frustration with date fields that are anything other than a plain text field for well known dates (like birthdays). They can anger users. Enough that I have seen users quit a test (more than once).

Users do not want to have to stop their flow and learn this new user interface. They don’t want to experiment to see what keys work, or read a pile of instructions. They want to enter a date and move on. This applies just as much to native date pickers. They may only use their phone or computer to email and surf the web, not enter extensive date-specific information on a regular basis.

A developer may use a date picker a few times a day. Every few minutes when building a screen with a date picker. Heck, maybe only once or twice a week. But a developer may have used date pickers in one month far more times than an average user in a year or a lifetime.

Accessibility

I have not touched on the accessibility issues with date pickers. The ones that claim to be accessible aren’t.

For example, we know <input type="date"> is a problem for voice users across browsers. Graham Armfield already produced a thorough report on the accessibility of the native control and came to conclusion that nope, it is not accessible.

I am constantly tossed date pickers from libraries and asked to evaluate them, and they are typically an accessibility quagmire. There is a reason most accessibility professionals tense up at the mention of date pickers.

Unnecessary detail about one library’s date picker…

I gathered the following notes after only a few minutes with the ReactJS Datepicker and its accessibility notes. I am reasonably confident more issues would be found with more time.

  1. The buttons at the top of the grid to navigate to the previous or next month have no accessible name. If a screen reader user gives them focus, they will be announced only as “Button”. This is a WCAG 4.1.2 violation.
  2. The arrows in the buttons have insufficient contrast with the background, meaning users in sunlight, with poor monitors, or with low vision may have trouble seeing them. This is a WCAG 1.4.11 violation.
  3. The <select> menus for the month and year have no accessible name (via <label>, aria-label, or otherwise). A screen reader user will hear the current value, but no label. While the value may provide context for the field, it does not provide context in the overall control. This is a WCAG 1.3.1 and 3.3.2 violation.
  4. The site provides a stack of keyboard shortcuts that the calendar control supports. While supported, nowhere is that support conveyed to users. Keyboard-only and screen reader users are provided no instructions on how to use the control, meaning they will likely arrow their way through months and years to find their choice. This is a WCAG 3.3.2 violation.
  5. The previous / next month buttons, the month select and the year select cannot be accessed by a keyboard-only user. Using the arrow keys does not put focus on those controls. Using Tab moves the focus to the next field of the form. Of the listed supported keyboard shortcuts, even if a keyboard-only user knew about them, there is no way to get to those visible controls, meaning they will likely arrow their way through months and years to find their choice. This is a WCAG 2.1.1 violation.
  6. The dates have an aria-label with them that overrides the visible text and adds complexity to the term. While aria-label typically will not work on a <div>, the role makes it work. In this case, instead of a screen reader user hearing “18” they hear “day dash 18”. A better approach would be to exclude the aria-label altogether. This is not a technical WCAG violation, but is considered a usability issue for screen reader users.
  7. The currently selected date is not conveyed to screen reader users. It is only conveyed visually. This is a case where aria-label may be useful to convey the state of the calendar date, perhaps as aria-label="18 selected". It is possible aria-current can work here. As it is, this is WCAG 1.4.1 and 4.1.2 violation.
  8. The week days are not conveyed to screen reader users for individual days. Because the calendar does not use a <table> with <th> elements for each weekday, and because arrowing right or left moves the user regardless of the start or end of a row, a screen reader user will not know if a particular date falls on a Monday, Tuesday, etc. It does not help this is also mis-cast with role="listbox". This is a WCAG 1.3.1 violation.

Round-up of WCAG violations in this calendar control as listed above:

  • 1.3.1: Info and Relationships (A)
  • 1.4.1: Use of Color (A)
  • 1.4.11: Non-text Contrast (AA)
  • 2.1.1: Keyboard (A)
  • 3.3.2: Labels or Instructions (A)
  • 4.1.2: Name, Role, Value (A)

Validation

Using third-party or native calendar controls can make a developer feel that the validation is handled. Handled by the collective intelligence of everyone who worked on the control.

But the developer still has to provide validation outside of the control. Sometimes validation is needed to support the fallback state for older browsers. Sometimes it is there to honor progressive enhancement. But mostly there should be server-side validation because we know scripts break and resources don’t load and data can be bypass client-side validation.

I cannot imagine that developers are going to let user-submitted content directly into their data structures without scrubbing it in some minimal way. And not just because of the fear of Little Bobby Tables paying their site a visit. As a skilled user, I can get around confounding controls by injecting the values I want using the browser’s dev tools, and developers typically account for data coming through outside of the carefully crafted client-side validation.

The point is, robust web sites and applications already do validation on the data outside of that provided by the control.

An Alternative to Date Pickers

Users generally do not want a complex date picker every time you ask for any date. At least not users with a keyboard.

Text Field

Previously I have relied on plain text inputs as date fields with custom validation for the site, typically using the same logic on the client and the server. For known dates — birthdays, holidays, anniversaries, etc — it has tested well.

Text Field with Messaging

In this prototype I am still using a text input for the first field, but I also use client-side script to convert the data to a human-readable date that I present to the user. This way a user can get immediate feedback and worry a bit less about matching a specific arcane data format the developers prefer.

In short, I am trying to deliver far less code (and confusion) to the end user while accepting a broader range of date formats. I am letting the robustness principle drive my approach.

Prototype

See the Pen XQBgNO by Adrian Roselli (@aardrian) on CodePen.

You will note that I ask for a U.S. date format. The weirdest one. This can be adjusted, of course, but I chose it to demonstrate how a globally confusing format benefits from immediate feedback.

The script to convert the date is the minimal amount of code to demonstrate the effect. It is not production-ready. It is not even good. Try it by entering “7 5 19”. Ideally, the date your script generates is the one you submit with the form.

Note the ARIA attributes, the connections between the fields, and use of <output> to hold the message. These are all there to make sure it is useful for screen reader users and voice users.

    <label for="BDay01" id="BDay01Label">Birth date <span>(MM/DD/YYYY)</span>:</label>
    <input type="text" id="BDay01" aria-labelledby="BDay01Label BDay01error" aria-describedby="BDay01confirm" onblur="valiDate(this.id,'BDay01confirm','BDay01error');">
    <output class="confirm" id="BDay01confirm" aria-live="assertive" for="BDay01" form="Form"></output>
    <div class="error" id="BDay01error"></div>
Update: 10 July 2019

For more on <output>, read Scott O’Hara’s post <output>: HTML’s native live region element.

Testing Feedback

Dragon Dictate users are generally frustrated with all calendar controls, including the native ones we get from type="date". In an informal test, this one proved usable.

Informal tests (anecdata) from other users showed this approach was no worse than a text field and far easier than a calendar control.

Places This Will Not Work

There are plenty of situations where a plain text field (with or without the messaging feature I prototyped) will not work.

If you need to see chosen dates, unavailable dates, weekends, holidays, date spans, date ranges, dates where counts from start or end dates matter, and so on.

Wrap-up

What we know is that native and custom calendar controls are often a problem for users and applied where they are not needed. Before dropping the code on a screen as a matter of habit, consider if it genuinely helps the user or just your workflow.

I do not propose a perfect solution for the narrow use case I identified, but I am hoping it spurs rethinking the casual application of a more complex pattern than is often warranted.

Update: 20 June 2020

Tommy Feldt has put together a proof of concept that works similarly to my example (mine outputs as text, this one to a calendar view). You can find his Inclusive Dates datepicker on GitHub and play around with the demo.

If you play around with it you will see it handles odd dates similarly to mine (try 02/31/1995 from the comments below). I suggest you test it for localization support (honoring dates in your locale).

The calendar uses a native <table> but neuters the semantics with role="presentation" (as opposed to using a grid role, if any change was needed). So I would consider adjusting that.

Update: 13 August 2020

In the post Natively Format JavaScript Dates and Time, Elijah Manor talks about native JavaScript functions such as toLocaleDateString(), toLocaleTimeString(), and toLocaleString() (which I use in my demo).

Sadly, it leans on screen shots without alt text and a video sans captions, but the content may be helpful to understand different ways you can use these functions that might fit your use case. Particularly if JavaScript is normally not your thing.

Update: 10 October 2023

Russ Weakley gave a talk at ID24 2023 (its 11th edition!) titled, “What makes an accessible date picker? Is it even possible?” He does not offer a final product; instead he walks through factors authors must consider before even writing code. I have embedded it:

He uses the birth date use case I talk about above, too.

25 Comments

Reply

Great post!

What do you think about having a solution like this, plus a button next to it that launches a date picker for those that want it?

In response to James. Reply

I think that is fine. Forcing the date picker is not, but letting users choose gives them flexibility. For one-off cases, you may want to let them know in the instructions as some users will not be aware there is an option until after they fill out the date field.

In response to James. Reply

I think a datepicker adds unnecessary payload, JS is what slows a page down most.
use the date input to the fullest with min, max, list & datalist, placeholder=”yyyy-mm-dd” if the min & max value changes due to some range logic then you must also add complicated logic to change the picker also

beside, the input comes with a date picker built in…

Jimmy; . Permalink
In response to Jimmy. Reply

From above on the native date input:

For example, we know <input type="date"> is a problem for voice users across browsers. Graham Armfield already produced a thorough report on the accessibility of the native control and came to conclusion that nope, it is not accessible.

Reply

Love the idea of being able to enter a date in any way you choose, and letting the browser decode it, and return a date (eg. 1 January 2019) as confirmation.

It would be a great opportunity for browsers to take up the slack there too, updating type="date" with regional variations etc.

But maybe, like James says above, having a calendar button as an additional option.

Great post.

Reply

What do you think about a text field with input mask?

Bora Arat; . Permalink
In response to Bora Arat. Reply

I am not a fan of input masks. Some implementations use the value of the field, which can be confusing for screen reader users (including sighted SR users). Some use the placeholder attribute, which has the same problem and is sometimes invisible to low-vision users. Most display characters that are disallowed or otherwise skip over those characters, which can be problematic for those with mobility or cognitive impairments. I have seen users struggle with them in nearly every case where I have tested them.

Reply

Hi, thanks for the post. I really cannot believe that there is not an off-the-shelf option to have a field that captures known dates (like birth date).
I understand the datepicker option for things like selecting flights or planning a future date but in data capture from something like a form.
I’ve tried bootstrap, asp.net, html etc and none seem to allow one to simply switch off the picker.
Have you considered releasing something like this?

Ken; . Permalink
In response to Ken. Reply

Ken, why not <input type="text"> as I outline above in my example? Look for date validation in your framework of choice instead of relying on my sub-par script.

Reply

Hi,
Nice post, I appreciate so thank you for it!
I am a teacher of blind users and students and I have problem with the dates everydaily.
So your text solution using javascript validation is fine, but when I put in date field wrong date such as 02/31/1995 it tolds me: You entered March 3, 1995.
So I assume that js validation script moves to next apropriate day and month.
Could it be fixed?
I it will be very useful for blind users that could be confused and to enter wrond data in forms.
Kind regards.
Iliya

Iliya; . Permalink
In response to Iliya. Reply

Iliya, the script I wrote is not production-ready. For example, as you discovered, it tries to convert the string to a valid date, which in this case it does.

If you are hoping to implement it or something similar in your own project, I suggest you work with a developer on the project to write a script that does what you need. There may already be something in their library that can do it.

Reply

Hi,

How can i use the script for EU date format DD-MM-YYYY?

Can’t find in de js the validation i can change it.
Changed (locale = “en-us”), tot “nl-NL” but don’t work for the format. Only the test confirmation language

In response to Frank. Reply

Frank, the code in my example is only for demonstration purposes. You should not use it in production. If you just want to play around, consider changing the lang attribute on the <html> element to see if that does what you want.

In response to Adrian Roselli. Reply

Thnx for the quick response…don’t use the whole script for production, but parts of it.

Tried define the language in the html attribute, but unfortunately still US date format.

Frank Scholte; . Permalink
In response to Frank Scholte. Reply

Didn’t show the code i also typed in the post. Put now ( ) on it for this website in hope to show it. I put lang=”nl in the html

( )

Frank Scholte; . Permalink
In response to Frank Scholte. Reply

Yeah, my comments field (intentionally) eats most script blocks. All the script does is parse a string to see if it is a date, then outputs that date based on the defined locale and my own string assembly. I would like to give you a quick answer, but dates in JavaScript are not my bag. I suspect you may find some of this work already done in some other validation scripts.

Reply

Great share! Would it be a good idea to use type="number" rather than type="text" so that it opens the numerical keyboard on mobile devices? I see you can also type the month name out, but could guess most people will be typing numbers.

In response to Maya Benari. Reply

That’s a good question and I think one that can only be answered by understanding the audience. If I am putting it on a site for teaching computer skills that is only accessed from libraries, maybe not. If 99% of my traffic comes from mobile, maybe so. For everything between… test?

Reply

I am veering toward a plain text field, but I wondered if it was a cognitively lower bar and easier for the small screen user to have three native HTML SELECT elements, [YEAR] [MONTH] [DAY]. So again, very basic like the plain text field but not having people look for their forward slash on their mobile keyboard, and breaking down their “work” into three tap+swipes.

I can’t help but assume I’ve missed something and the above is likely somehow worse than a plain text field, but I would greatly appreciate your view.

Alan Bristow; . Permalink
In response to Alan Bristow. Reply

I wondered if it was a cognitively lower bar and easier for the small screen user to have three native HTML SELECT elements, [YEAR] [MONTH] [DAY].

Select menus are almost always a greater cognitive (and physical) load. Test with users and I am confident you will confirm that.

So again, very basic like the plain text field but not having people look for their forward slash on their mobile keyboard, and breaking down their “work” into three tap+swipes.

It is not three taps/swipes. Consider removing the requirement for slashes. Allow for any or no character. Consider a masked field if it tests well enough. And so on.

Reply

Great, thank you Adrian.

After posting here I also found the same advice on an NNG page and then, for my use-case, the ideal pattern — plain text fields, one per item of data — over on these two GOVUK pages: page1 and page2.

Aside: there, on GOVUK I also learnt about inputmode="numeric" and, for date of births, autocomplete="bday-day", bday-month and bday-year. I find I am oten delighted and amazed by the amount of (important) detail there is to find in such small parts of HTML when you keep looking.

Alan Bristow; . Permalink
In response to Alan Bristow. Reply

Indeed, the controls that seem simplest are often the trickiest. Glad you have some more resources to use.

Reply

So, I’ve been thinking about this and I’ve been fiddling with a numeric date string parser that will attempt to parse any numeric type date string: https://github.com/area17/parse-numeric-date
So, you can input 2022-10-02 or 2/10/22 or even something as ambiguous as 21022 and it will try parse.

Reply

Hey, we are now a few years from the post-published date, and I wonder if your opinion changed or if you kept testing date pickers with other users.

Do you still see using the date picker for simple cases as a suboptimal option, or there’s a good component these days that can provide the same level of experience for all users?

Thank you!

Djalma; . Permalink
In response to Djalma. Reply

Hey, we are now a few years from the post-published date, and I wonder if your opinion changed or if you kept testing date pickers with other users.

Nope and yup!

Do you still see using the date picker for simple cases as a suboptimal option, or there’s a good component these days that can provide the same level of experience for all users?

I have not found an ideal date picker yet (which doesn’t mean it doesn’t exist). Even if I did, however, I still would not use it for simple cases like I cite here.

Leave a Comment or Response

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>