Skip to content

DigitalA11Y

Your Accessibility Partner

  • Home
  • ServicesExpand
    • WCAG Audit Services
    • VPAT/ACR Services
    • Accessibility Consulting
    • PDF Remediation
    • Accessibility Trainings
    • Website Remediation
    • Design Audit
  • Free ToolsExpand
    • Accessibility Checker
    • A11Y Cost Calculator
    • A11Y Bookmarklets
    • Color Contrast Extension
    • WCAG Contrast Checker
  • ResourcesExpand
    • A11Y Articles
    • WCAG Primer
    • ARIA Cheatsheet
    • A11Y Tools
    • A11Y Patterns
    • A11Y Cheatsheets
  • Contact
Search
DigitalA11Y
Your Accessibility Partner
Search

Form Validation with Messages on Top

Data submitted in a form is usually validated in some way. And if there is any unacceptable data, the form is traditionally re-displayed, together with validation messages. In such a case, it is important to immediately inform screen reader users, so they know that they have to look at their data and submit again.

The following example is very similar to the one above, except in this use case, all messages are displayed inside a <fieldset> / <legend> structure on top of the form. Each message is an in-page link, targeting the respective invalid input.
In addition to this, each invalid input is associated to its message using aria-describedby. This is important, as it makes sure that screen readers also announce the messages when navigating through the inputs.

Working Example

    Gender:

    Explanation

    If there are any validation messages, the focus is set to the first message: this way, a screen reader will immediately announce it, so the user knows that there is at least one invalid input to be fixed. As the message is also announced as “in-page link”, the user can activate it and jump to the respective input; but the user also may decide to stay in the messages block and read the other messages before fixing any of the inputs.

    After fixing the invalid input, the user can search for other invalid ones or simply submit the form again to repeat the process.

    Our examples above are very simple and created mainly to demonstrate screen reader usage. Please optimize your own form controls and validations for other
    users, too.

    • For example, add colours and other visual attributes to invalid fields, for example, a thick colored border, a decent background color, etc.
    • Graphical icons can be a useful indicator, too, for example, a fancy exclamation mark.
    • It is also important to provide users with meaningful messages that help them fix their input: while “Incorrect input format” is not very helpful for a date input, something like “Please enter in format YYYY/MM/DD” is much better.

    Code

    • HTML
    • CSS
    • JavaScript
    <div id="error-container" role="alert" aria-live="polite">
        <ul class="error-list"></ul>
    </div>
    <form id="contactForm" onsubmit="return validateForm()">
        <div class="form-control">
            <label for="name">Full Name:</label>
            <input type="text" id="name" name="name" aria-describedby="nameError">
        </div>
    
        <div class="form-control">
            <label for="email">Email:</label>
            <input type="email" id="email" name="email" aria-describedby="emailError">
        </div>
    
        <div class="form-control">
            <label for="message">Message:</label>
            <textarea id="message" name="message" aria-describedby="messageError"></textarea>
        </div>
    
        <div class="form-control">
            <fieldset>
                <legend>Gender:</legend>
                <input type="radio" id="gender-male" name="gender" value="male" aria-describedby="genderError">
                <label for="gender-male">Male</label>
                <input type="radio" id="gender-female" name="gender" value="female" aria-describedby="genderError">
                <label for="gender-female">Female</label>
            </fieldset>
        </div>
    
        <div class="form-control">
            <input type="checkbox" id="accept-terms" name="accept-terms" value="1" aria-describedby="termsError">
            <label for="accept-terms">I accept the terms and conditions</label>
        </div>
    
        <div class="form-control">
            <input type="submit" value="Submit">
        </div>
    </form>
    <script>
        function validateForm() {
            var name = document.getElementById("name").value;
            var email = document.getElementById("email").value;
            var message = document.getElementById("message").value;
            var gender = document.querySelector('input[name="gender"]:checked');
            var acceptTerms = document.getElementById("accept-terms").checked;
    
            var errors = [];
    
            if (name.trim() === "") {
                errors.push("name");
            }
    
            if (email.trim() === "") {
                errors.push("email");
            }
    
            if (message.trim() === "") {
                errors.push("message");
            }
    
            if (!gender) {
                errors.push("gender");
            }
    
            if (!acceptTerms) {
                errors.push("accept-terms");
            }
    
            if (errors.length > 0) {
                displayErrors(errors);
                return false;
            }
    
            return true;
        }
    
        function displayErrors(errors) {
            var errorContainer = document.getElementById("error-container");
            var errorList = document.querySelector(".error-list");
    
            errorList.innerHTML = ""; // Clear existing errors
    
            errors.forEach(function (fieldName, index) {
                var errorLinkId = "error-link-" + index; // Generate unique IDs for error links
                var listItem = document.createElement("li");
                var errorLink = document.createElement("a");
                errorLink.textContent = "Error in " + fieldName;
                errorLink.className = "error-message";
                errorLink.href = "#"; // Make it focusable
                errorLink.id = errorLinkId; // Set the unique ID
                errorLink.addEventListener("click", function (e) {
                    e.preventDefault();
                    moveFocusToField(fieldName);
                });
                listItem.appendChild(errorLink);
                errorList.appendChild(listItem);
    
                // Associate the error link with its corresponding form field using aria-describedby
                var field = document.querySelector('[name="' + fieldName + '"]');
                if (field) {
                    field.setAttribute('aria-describedby', errorLinkId);
                }
            });
    
            errorContainer.style.display = "block"; // Show error container
            document.getElementById("error-link-0").focus(); // Focus the first error link
        }
    
        function moveFocusToField(fieldName) {
            var field = document.querySelector('[name="' + fieldName + '"]');
            if (field) {
                field.focus();
            }
        }
    </script>

    Company

    • About
    • Blog
    • Careers
    • Contact

    Services

    • Accessibility Audits
    • Accessibility Consulting
    • VPAT/ACR
    • Accessibility Trainings

    Compliance

    • WCAG
    • ADA
    • Section 508
    • EN 301 549
    • EAA
    • AODA
    • ACA

    Resources

    • Accessibility Resources
    • Understanding WCAG
    • WCAG Checklist
    • Understanding WAI-ARIA

    Legal

    • Privacy Policy
    • Terms and Conditions
    • Disclaimer
    • Accessibility Statement for digitala11y.com
    • Sitemap

    © 2025 DigitalA11Y
    All Rights Reserved

    Linkedin Twitter Facebook Instagram YouTube

    DigitalA11Y
    Plot No 108, 3rd Cross Rd, Saipuri Colony,
    Hastinapuri Colony, Sainikpuri, Secunderabad -500094
    Telangana, India.

    Tel:(+91)99082 66680,
    E-mail: [email protected]

    Scroll to top
    • Home
    • Services
      • WCAG Audit Services
      • VPAT/ACR Services
      • Accessibility Consulting
      • PDF Remediation
      • Accessibility Trainings
      • Website Remediation
      • Design Audit
    • Free Tools
      • Accessibility Checker
      • A11Y Cost Calculator
      • A11Y Bookmarklets
      • Color Contrast Extension
      • WCAG Contrast Checker
    • Resources
      • A11Y Articles
      • WCAG Primer
      • ARIA Cheatsheet
      • A11Y Tools
      • A11Y Patterns
      • A11Y Cheatsheets
    • Contact