I've implemented a custom validation message on my input for the pattern validation rule while leaving the default message for required as is. However, when I do so, once the input becomes invalid, it never becomes valid again, even though I am meeting the pattern criteria.
document.addEventListener("DOMContentLoaded", function () {
const txtUsername = document.getElementById("UserName");
txtUsername.oninvalid = function (e)
{
const input = e.target;
if (input.validity.patternMismatch)
{
input.setCustomValidity("Usernames cannot contain the @ symbol");
}
}
})
<form onsubmit="event.preventDefault(); alert('Form submitted');" action="post">
<!--pattern regex prohibits use of the @ symbol-->
<input id="UserName" type="text" pattern="^((?!@).)*$" required />
<button type="submit">Submit</button>
</form>
When I remove my custom oninvalid event handler, this issue does not occur. What am I doing wrong?
One additional question, though not essential to me resolving this issue: why does Chrome's built in validation pop-up text animate in so slowly and choppy, almost as if there's some sort of performance bottleneck? My machine is powerful and has no issues with any other type of graphical processing.

First of all, per MDN:
This agrees with that the HTML standard says:
Your sample does not clear the custom error if the form field is determined to be valid. As such, once the field is determined invalid, it stays so for the remainder of the session.
Moreover, you modify custom error only after the field has already been determined invalid. This means the form will still not be submitted even if you clear the message in the same handler.
A better way to accomplish your goal would be to monitor the field in the
changeevent handler for the field and set the custom message there: