Date Picker
- Date picker is an alternative way to enter date in forms.
- Users can select a date from the calendar.
NOTE:
- New to accessibility or uncertain of requirements, it will be helpful to review all sections below.
- Already familiar with requirements, skip to the “Working Example” section for sample HTML, CSS and JavaScript (when needed), along with a working demo.
Date picker CAN be implemented using following approaches:
HTML:
- Date picker MUST be defined using
<input type="date">
element. - A descriptive visual label MUST be provided for the date input field. See “Label placement and structure” component for more information on labelling.
- The correct date format CAN be mentioned immediately below the date input field and the same SHOULD be referenced using aria-describedby attribute defined for the date input field. Alternatively, it CAN be a part of the label text itself.
- Color requirements MUST be met for the visual label or instructions if any as mentioned in the “Label placement and structure” component.
- Enter the date in the input field using keyboard.
-
A calendar icon is displayed within the input field for the native approach.
Note: A calendar appears by clicking the calendar icon, that helps users to choose the respective date. -
The value attribute CAN be used to display the default date. Its default format is
yyyy-mm-dd.
Note: If the date format of the user’s system (locale) is different from the default mentioned in value attribute, then the displayed date will take the format of the user’s system. - The min and max attributes CAN be used to set the range of acceptable dates.
For example,
<label for="datepick"> Select Date (mm/dd/yyyy): </label>
<input type="date" id="datepick">
ARIA:
Though ARIA CAN be used as an alternative, it is advisable to use correct semantic HTML element since native elements have built-in keyboard accessibility, roles and states.
- The date picker can be accessed by an image button placed towards the right of the date input field.
-
Accessible name MUST be defined for the image button.
-
If the image is defined using
<img>
element, use alt attribute with descriptive value. -
If the image is defined using
<svg>
element, userole="img"
and aria-label attribute to provide an accessible name and role for the element.
Note: Providing ARIA based role and attribute on SVG image ensures robust support across different environments.
-
If the image is defined using
-
The date widget MUST be contained within a modal dialog.
-
The neutral container such as
<div>
element MUST have arole="dialog"
. -
The accessible name for the dialog MUST be provided using aria-label
attribute on the
<div>
element. -
The
aria-modal="true"
attribute MUST be provided for the<div>
element of dialog. - When the calendar image button is activated, focus SHOULD move to the selected date. In the absence of a selected date, focus SHOULD move to the current date.
- When the calendar is closed, the focus SHOULD return to the triggering element i.e., calendar image button.
- The focus SHOULD be restricted within the modal dialog.
-
The neutral container such as
-
Image buttons such as “Previous year”, “Previous month” and “Next
year”, “Next month” image buttons MUST be defined to change the
years and months respectively.
- When the month/year is changed, the focus SHOULD remain on the respective button.
- The informative images such as “Calendar” icon, “Previous year”, “Previous month” and “Next year” and “Next month” SHOULD be visible in High Contrast Mode as well.
- On selecting a date, the date widget SHOULD be closed, and the selected date gets populated in the date input field. Alternatively, “Ok” and “Cancel” buttons can be provided for users to submit or cancel the value respectively.
-
The current date MUST be provided with
aria-current="date"
attribute. -
The selected date MUST be provided with
aria-selected="true"
attribute - The current and selected dates MUST be denoted with additional visual cues such as underline, bold text, icon and so on along with color.
- The contrast requirement of 3:1 ratio MUST be met with the adjacent colors for the image buttons.
- The contrast requirement of 4.5:1 ratio MUST be met with the adjacent colors for the dates including current and selected dates.
- The contrast requirement of 3:1 ratio MUST be met with the adjacent colors for the custom focus indicator of the interactive elements inside the date widget.
-
The
aria-live="polite"
attribute SHOULD be used for the container used for defining month name in the date widget. This ensures that the month name and/or year is announced by screen reader when it is changed. - The dates in the widget SHOULD be implemented using table or grid mark-up. The aria-labelledby attribute SHOULD be used for providing an accessible name for the grid. For more information on implementing grid markup, refer to Date Picker Dialog Example | APG | WAI | W3C
- Arrow keys SHOULD be used to navigate to the respective dates. While navigating through the dates, focus should be managed using roving tabindex. For more information, refer to Managing Focus Within Components Using a Roving tabindex .
For example,
<!-- Defining an input field -->
<label for="id-textbox-1"> Date </label>
<input type="text" placeholder="mm/dd/yyyy" id="id-textbox-1" aria-describedby="id-desc-1">
<span class="desc" id="id-desc-1"> (mm/dd/yyyy) </span>
<!-- Defining the date picker button -->
<button> <img src="…" alt="Choose a date"> </button>
<!-- Defining the modal dialog containing the calendar that appears on activating the date picker button -->
<div id="id-datepicker-1" role="dialog" aria-modal="true" aria-label="Choose Date">
<div>
<!-- Defining the Previous Month, Next Month, Previous Year and Next -->
<!-- Year buttons along with the current Month and Year text -->
<button> <img src="…" alt="Previous Year"> </button>
<button> <img src="…" alt="Previous Month"> </button>
<h2 id="grid-lbl" aria-live="polite"> March 2023 </h2>
<button> <img src="…" alt="Next Month"> </button>
<button> <img src="…" alt="Next Year"> </button>
<!-- Defining ARIA grid for the dates and days -->
<table role="grid" aria-labelledby="grid-lbl">
<thead>
<tr>
<th scope="col" abbr="Sunday"> Su </th>
<th scope="col" abbr="Monday"> Mo </th>
<th scope="col" abbr="Tuesday"> Tu </th>
<th scope="col" abbr="Wednesday"> We </th>
<th scope="col" abbr="Thursday"> Th </th>
<th scope="col" abbr="Friday"> Fr </th>
<th scope="col" abbr="Saturday"> Sa </th>
</tr>
</thead>
<tbody>
<tr>
<td class="disabled" tabindex="-1"> 26 </td>
<td class="disabled" tabindex="-1"> 27 </td>
<td class="disabled" tabindex="-1"> 28 </td>
<td class="disabled" tabindex="-1"> 1 </td>
<td class="disabled" tabindex="-1"> 2 </td>
<td class="disabled" tabindex="-1"> 3 </td>
<td class="disabled" tabindex="-1"> 4 </td>
</tr>
<tr>
<td class="disabled" tabindex="-1"> 5 </td>
<td class="disabled" tabindex="-1"> 6 </td>
<td class="disabled" tabindex="-1"> 7 </td>
<td class="disabled" tabindex="-1"> 8 </td>
<td class="disabled" tabindex="-1"> 9 </td>
<td class="disabled" tabindex="-1"> 10 </td>
<td class="disabled" tabindex="-1"> 11 </td>
</tr>
<tr>
<td class="disabled" tabindex="-1"> 12 </td>
<td class="disabled" tabindex="-1"> 13 </td>
<td class="disabled" tabindex="-1"> 14 </td>
<td class="disabled" tabindex="-1"> 15 </td>
<td class="disabled" tabindex="-1"> 16 </td>
<td class="disabled" tabindex="-1"> 17 </td>
<td class="disabled" tabindex="-1"> 18 </td>
</tr>
<tr>
<td class="disabled" tabindex="-1"> 19 </td>
<td class="disabled" tabindex="-1"> 20 </td>
<td class="disabled" tabindex="-1"> 21 </td>
<td class="disabled" tabindex="-1"> 22 </td>
<td class="disabled" tabindex="-1"> 23 </td>
<td class="disabled" tabindex="-1"> 24 </td>
<td class="disabled" tabindex="-1"> 25 </td>
</tr>
<tr>
<td class="disabled" tabindex="-1"> 26 </td>
<td class="disabled" tabindex="-1"> 27 </td>
<td class="disabled" tabindex="-1"> 28 </td>
<td class="disabled" tabindex="-1"> 29 </td>
<td class="disabled" tabindex="-1"> 30 </td>
<td class="disabled" tabindex="-1"> 31 </td>
<td class="disabled" tabindex="-1"> 1 </td>
</tr>
</tbody>
</table>
<!-- Defining the optional Ok and Cancel button -->
<button> Cancel </button>
<button> OK </button>
</div>
</div>
A well-defined date picker benefits majorly the below users.
- People with cognitive disabilities
- People using speech input
- People with limited dexterity
- People using keyboard only
- People using screen readers
<div>
<label for="datepick">Select Date (mm/dd/yyyy):</label>
<input type="date" id="datepick" class="datePicker">
</div>
label {
display: block;
margin: 2px;
font-size: 18px;
}
.datePicker {
padding: 4px;
width: 17%;
}