Accessibility

A red border tells a sighted mouse user something is wrong. It tells a screen reader user nothing at all. Since 3.0 every error this plugin shows is also reported as text, associated with the field it belongs to.

This is on by default

There is nothing to enable. The only related option is focusOnError, which is already true.

What the plugin emits

FeatureBehaviour
aria-invalidSet to "true" on a failing field, in both inline and summary modes. Removed — not set to "false" — once the field passes, so an unvalidated field makes no claim either way.
aria-describedbyPoints the field at the element holding its message, so a screen reader reads the reason when the field is focused.
aria-live="polite"On inline messages, so an error appearing on blur is announced without interrupting what the visitor is typing next.
role="alert"On the error summary.
Focus managementOn a failed submit, focus moves to the summary, or to the first invalid field in inline mode.
aria-busyOn a field while an asynchronous check is in flight.
Reduced motionHelp-text fades are skipped when the visitor has asked for reduced motion.

Your aria-describedby is preserved

Fields often already point at hint text. The plugin appends its own token rather than replacing what is there, and on cleanup removes only the token it added.

HTML
<label for="pw">Password</label>
<span id="pw-hint">At least 12 characters.</span>
<input id="pw" type="password" aria-describedby="pw-hint"
       data-validation="strength">
What the plugin produces
<!-- While invalid -->
<input id="pw" aria-describedby="pw-hint jfv-error-pw-1" aria-invalid="true">

<!-- Once corrected — your hint survives -->
<input id="pw" aria-describedby="pw-hint">

The error summary

With errorMessagePosition: 'top' the plugin renders one summary above the form. It is a role="alert", receives focus on a failed submit, and every entry is a link to the field it describes — so the summary can be navigated by keyboard, not merely read.

JavaScript
$.validate({
  errorMessagePosition: 'top'
});
What the plugin produces
<div class="form-error alert alert-danger" role="alert" tabindex="-1">
  <strong>Form submission failed!</strong>
  <ul>
    <li><a href="#email">You have not given a correct e-mail address</a></li>
    <li><a href="#jfv-field-age-1">The input value is shorter than 2 characters</a></li>
  </ul>
</div>

Fields without an id are given a generated one so the link has somewhere to point. That is what {id} means in the summary template.

Prefer the summary on longer forms

When a failed submit produces several errors at once, one focusable list is far easier to work through than hunting for messages scattered down the page. It is also the pattern most assistive technology users will recognise.

What the theme handles

The bundled stylesheet was corrected in 3.0 to meet WCAG 2.2 AA:

  • Contrast. Error text is #843534, which clears 4.5:1 against the summary background. The previous #b94a48 managed only 3.93:1.
  • Not colour alone. Invalid fields carry an icon as well as a red border, and inline messages are prefixed with a warning marker — WCAG 1.4.1.
  • Target size. Summary links are at least 24 px tall — WCAG 2.2 SC 2.5.8.
  • Reduced motion. Transitions and animations are disabled when the visitor has asked for that.
The plugin cannot label your fields

It reports errors accessibly, but it cannot invent a <label> you did not write. Every field still needs one, associated by for/id or by wrapping. That is the single most common form accessibility failure and it is outside what any validation library can fix.

Working with the browser

novalidate is added to the form by default, so the browser does not stack its own error bubbles on top of the plugin's messages. A novalidate attribute you wrote yourself is never removed.

Loading the native module mirrors every result onto the element, which means :user-invalid and form.checkValidity() agree with your rules — useful if your CSS already styles those states.

JavaScript
$.validate({
  modules: 'native',
  novalidate: true   // the default
});

Using the helpers yourself

If you take over error display with inlineErrorMessageCallback, the ARIA wiring is available so your own markup can behave the same way.

JavaScript
$.validate({
  inlineErrorMessageCallback: function ($input, errorMsg, conf) {
    var $slot = $input.closest('.field').find('.field-error');

    if (errorMsg) {
      $slot.text(errorMsg);
      $.formUtils.a11y.describeError($input, $slot);
    } else {
      $.formUtils.a11y.clearError($input);
    }

    return false;   // we rendered it ourselves
  }
});

Testing your forms

Automated checks catch some of this. These are the parts worth doing by hand:

  • Keyboard only. Submit an empty form. Focus should land on the summary, and each entry should take you to its field.
  • Screen reader. With NVDA, JAWS or VoiceOver, confirm the error is announced on blur, and that focusing a failed field re-reads the reason.
  • Zoom and reflow. At 200% zoom and 320 px width, messages should stay attached to their fields.
  • Colour. Turn on a greyscale filter. Every error should still be identifiable.
Where this was verified

The bundled theme and the markup the plugin emits were checked with axe-core against the project's own test forms, in both inline and summary modes, with zero violations attributable to the plugin. Your own markup — labels, headings, landmarks — is still yours to get right.