Validate on blur, not on every keystroke. A user typing their email should not see ‘invalid email’ before they finish the @.
Show errors inline, anchored to the field, in red with an icon. Repeat the constraint near the input (e.g. ‘at least 8 characters’) so the user does not have to fail to learn the rules.
Use the Constraint Validation API (:invalid, setCustomValidity) and let the browser handle keyboard focus on submit. Custom messages should still be friendly: ‘We need an email address’ beats ‘invalid format’.