Newsletter signup form
Form validation, the slow way.
A newsletter signup form with client-side validation. The exercise is less about the form itself and more about getting validation feedback right — timing, copy, and visual state.
The Challenge
Build a signup form with an email field and submit button. Validate the email on submit. Show an error state if invalid, a success state if valid.
Requirements:
- Show an error message for empty or malformed email
- Error appears below the field, not as an alert
- Input has a visible error state (red border, etc.)
- Success view replaces the form (not an alert)
- Responsive: form stacks on mobile
What I Learned
Validation UX has a timing problem. Showing errors on every keystroke is annoying. Waiting until submit means the user has to guess. The right balance: validate on blur (when the field loses focus), then update in real-time after first error.
input.addEventListener("blur", () => validate());input.addEventListener("input", () => { if (input.classList.contains("error")) validate();});Error State
.input.error { border-color: hsl(4, 100%, 67%); background-color: hsl(4, 100%, 96%);}
.error-message { display: none; color: hsl(4, 100%, 67%); font-size: 0.75rem; margin-top: 0.25rem;}
.input.error ~ .error-message { display: block;}Why It Matters
Forms are where users give you their trust. Getting the validation feedback wrong — too aggressive, too vague, poorly timed — erodes that trust immediately.