Forms: Using aria-invalid to identify failed fields
Features
Places an aria-invalid attribute for a field only if the input data is not in the expected format. These also have generic error text alongside but the text is not tied to the field.
Uses a standard generic error message against every field when no data is entered. The error message is tied to the form control using aria-describedby.
The error displayed for a past date (after Jan 1, 2000) is associated with the field via markup
Every form control that fails validation has a red border and an error icon to its right (placed via CSS) for visual reinforcement
Date is not a required field; today's date is filled in as default
The error message placed above the form is within a span tag with role=alert. The SPAN tagg is within an h2 and is read by NVDA and JAWS. VoiceOver reads it in iOS and OSX.
About the error messages
JAWS and NVDA expose a field with aria-invalid=true as "invalid entry".
VoiceOver with Safari on OSX or iOS reads out the field as "invalid data"
The field's label (or other accessible name) is announced before the "invalid" notification.
The field-specific error messages when associated with aria-describedby are read by JAWS and NVDA as one tabs to the fields. VoiceOver reads these automatically only in iOS ... the error message is announced after a slight pause after the label is read. In OSX on a MacBook Pro, the VO+Shift+h key combination causes the error text referenced by aria-describedby to be read by VoiceOver.