Validation is the moment your product tells somebody they are wrong. Everything else in a form is a request; this is the only part that is a judgement, and it is the part that gets designed last, usually by whoever is implementing the field.
That is why so many forms are unpleasant in the same specific ways. The rules are not hard. They are just nobody's job.
The three moments you can validate, and the one that is usually right
There are only three points at which you can tell someone a field is wrong, and the choice between them decides most of how a form feels.
While they type. This is the worst one and it is everywhere. Someone starts entering an email address and is told, at the letter b, that b is not a valid email address. They know. They are three characters into a task and the product is already interrupting to say they have failed at it. The pattern is common because it is the easiest to implement and it demos well on a full, correct value.
When they leave the field. This is the right default. They have finished the thought, moved on, and the check happens at a natural boundary. It is also the last moment at which fixing the problem is cheap, because they are still in the neighbourhood.
When they submit. Necessary, because some things can only be known then, and because anything the earlier checks missed has to be caught. But as the primary mechanism it is the one that produces a screen of red at the end of five minutes of work.
The nuance worth adding: once a field has been marked wrong, switch it to validating as they type. The interruption was already made, so there is nothing left to protect them from, and now live feedback is genuinely useful because it can tell them the moment they have fixed it. Strict on blur, forgiving on return. That single rule fixes most of what people hate about validation without changing anything else.
Password fields are the standing exception. Requirements shown live, from the first keystroke, as a checklist that ticks itself off. Not because live validation became good, but because the alternative is guessing at rules that were never stated, and the field hides its own contents while you do it.
Error messages, and the thing they must contain
An error message has one job: get the person to a valid value. Almost everything that fails does so because it describes a state instead of an action.
"Invalid input" describes a state, and an obvious one. The person can see the field is not accepted; they wanted to know what would be. "Enter a date in the past" describes the action. That is the whole distinction, and applying it rewrites most error copy in a product.
Some things that follow from it:
Say what is wrong with this value, not what the rule is in general. "Passwords must be at least twelve characters" is a rule. "Your password is eight characters, it needs twelve" is the same rule with the person's actual situation in it, and it is shorter to act on.
Do not blame, and do not apologise. "You entered an invalid email" puts it on them. "Sorry, something went wrong" tells them nothing and takes a sentence to do it. "This does not look like an email address, check for a missing @" is neither, and it is the only one of the three that helps.
Name the field if the message can be seen away from it. A summary at the top of a form saying "This field is required" five times is not a summary.
Do not make the message the only signal. Red text alone fails anyone who cannot distinguish it. The message, the position and a change in the field's border together mean the colour is reinforcement rather than the message itself.
Where the message goes, and why it is not above the field
Below the field, attached to it, permanently occupying its space.
Below rather than above, because a message above the field pushes the field down at the moment someone is looking at it, and their pointer or their eye is now aimed at empty space. Attached rather than floating, because a message in a tooltip disappears the moment you interact with the thing it describes, which is exactly when you need it.
Permanently occupying its space is the one that gets skipped. If the message appears into space that was not reserved, every field below it moves. Fill in a form of eight fields, make two mistakes, and the layout is now dancing. Reserve the line whether or not there is a message in it. It costs a few pixels of vertical rhythm and removes a whole class of jumpiness, which is the same argument as reserving space for an image before it loads.
For long forms a summary at the top earns its place, but only if each entry is a link that moves focus to the field it names. A summary that lists problems without taking you to them has made the person do the search twice.
Disabled submit buttons are a trap
The pattern is intuitive: the form is not valid, so the button that submits it is disabled. It is also one of the more reliably frustrating things in interface design.
A disabled button gives no reason. Someone who cannot tell which of eleven fields is unfinished is now hunting, and the control that would have told them is the one you switched off. It is also invisible to a keyboard, since a disabled button cannot be focused, so a screen reader user reaches the end of the form and finds nothing there at all.
The better version: keep the button enabled, and on submit, validate everything, show every message, and move focus to the first field with a problem. The person gets an answer to the question they asked, which was "am I done", and the answer comes with directions.
The one case for disabling is an action already in progress, where a second press would submit twice. Even then the label should say what is happening rather than just going grey.
The validation you should not be doing
A meaningful share of validation exists to protect a database schema, and it is the person filling in the form who pays for it.
Whitespace and formatting. Rejecting a card number because someone typed the spaces that are printed on the card, or a phone number because of the brackets, is a rule that makes a computer's job marginally easier by making a person's job harder. Strip it and move on. I have written more about where this specifically costs money in payment flows.
Name fields. Names contain apostrophes, hyphens, spaces, accents and characters outside the Latin alphabet, and are sometimes one word. Length limits and character restrictions on a name field are almost always a bug wearing a rule.
Addresses. Formats that are mandatory in one country do not exist in another. A required postcode field breaks for anywhere that has none, and a fixed shape for a house number breaks a lot of Europe.
Email, beyond the obvious. There is an actual specification, it is more permissive than any regular expression you will write, and the strict ones reject valid addresses at a much higher rate than they catch typos. Check that there is an @ with something either side, then stop. If you need to know the address works, send to it; nothing else proves it.
The test I use: does this rule prevent a real problem, or does it prevent an inconvenience for the system? Only the first kind is worth an error message.
Small things that add up
Autocomplete and input types. The right autocomplete value and the right inputmode mean a browser fills the field and a phone shows the correct keyboard. This is the cheapest improvement in forms and the most frequently missing.
Never clear the field. Clearing a wrong value on failure is still out there, and it is the single most hostile thing a form can do.
Say what is optional, not what is required. If most fields are required, marking the exceptions is less noise than marking the majority.
Let the format be flexible and normalise afterwards. Dates, phone numbers, card numbers, postcodes. Accept what people type, tidy it up yourself, show them the tidied version so they can confirm.
What it comes down to
Every rule above is one thing said differently. A form is a conversation in which the product is asking for something, and validation is the part where it responds. A response that says "no" and stops is not a conversation, it is a door.
The forms I have worked on that performed best were not the ones with the fewest fields. They were the ones where being wrong was cheap: fast to discover, obvious to fix, impossible to lose your work to. That is a design property, and it is decided entirely by choices that are usually made in an afternoon by whoever picked up the ticket.