Validation is mostly a question of timing. Tell people what passes before they start, confirm success the moment it happens, and hold errors until they've had a fair chance to finish.
Show success as soon as a value is valid, but wait for the reader to leave the field before showing an error. Once a field is in error, re-check on every keystroke so the error clears the instant it's fixed.
A failed submit moves focus to a summary at the top that counts the problems and links each one to its field. Inline messages stay too: the summary is for finding errors, the inline message is for fixing them.
If a field has rules, they're part of the label, not the error. List them up front and tick each one off as it's met, so nobody has to fail to learn what passes.
Username
syntaqx