Form Validation UX Patterns

matt
Matthew Gros · Sep 4, 2025

TLDR

Validate on blur not keyup, show errors near fields, be specific about requirements, allow correction.

Form Validation UX Patterns

Validation Should Help, Not Annoy

Good UX makes forms easy to complete.

When to Validate

On blur (leaving field): Best for most fields On submit: Always, as final check On input: Only for specific cases (character count)

// On blur
input.addEventListener('blur', () => validateField(input));

// On submit
form.addEventListener('submit', (e) => {
    if (!validateForm()) {
        e.preventDefault();
    }
});

Show Errors Near Fields

<div class="field">
    <label for="email">Email</label>
    <input type="email" id="email" aria-describedby="email-error">
    <span id="email-error" class="error" role="alert">
        Please enter a valid email address
    </span>
</div>
.error {
    color: #dc2626;
    font-size: 0.875rem;
    margin-top: 0.25rem;
}

Be Specific

// Bad
"Invalid input"

// Good
"Email must include @ symbol"
"Password must be at least 8 characters"
"Phone number should be 10 digits"

Show Requirements Upfront

<input type="password" id="password">
<ul class="requirements">
    <li data-requirement="length">At least 8 characters</li>
    <li data-requirement="uppercase">One uppercase letter</li>
    <li data-requirement="number">One number</li>
</ul>

Inline Success

.field.valid input {
    border-color: #16a34a;
}
.field.valid::after {
    content: "✓";
    color: #16a34a;
}

Don't Block Typing

// Bad - prevents input
input.addEventListener('keypress', (e) => {
    if (!/\d/.test(e.key)) e.preventDefault();
});

// Better - validate after
input.addEventListener('blur', () => {
    if (!/^\d+$/.test(input.value)) {
        showError('Please enter numbers only');
    }
});

Preserve Input

After validation error:

  • Keep what user typed
  • Focus the first error field
  • Scroll to error if needed

About the Author

matt

I build and ship automation-driven products using Laravel and modern frontend stacks (Vue/React), with a focus on scalability, measurable outcomes, and tight user experience. I’m based in Toronto, have 13+ years in PHP, and I also hold a pilot’s license. I enjoy working on new tech projects and generally exploring new technology.