skip to Main Content

Normally the :invalid selector is evaluated instantly : The element will be styled immediately with :invalid for example if a value is required as soon as the page loads:

input:invalid {
  border: 10px solid red;
}
<form>
<p> Go red only after I focused and blurred away </p>
  <input required placeholder="you must type something" />
</form>

Would there be a workaround for this so that the evaluation happens only after the user interacts with the form? (typically, after the first focus / blur).
I understand this is standard browser implementation behavior so we’re likely looking for a workaround here.

Minimal JS is OK although I don’t want to do JS validation.

2

Answers


  1. A possible solution would be to combine multiple pseudo-classes to achieve the result, as explained here.

    Here’s an example (adapted from this Codepen) which shows the red border only if the value is invalid (in this case less than 3 characters in length).

    :root {
      --color-invalid: red;
      --color-valid: green;
    }
    
    .error-message {
        display: none;
    }
    
    /* Used for the demo to show that the input changes status (eg. passing from an invalid to a valid email address) */
    input {
      outline: none;
    }
    
    
    /* Invalid state */
    
    input:not(:placeholder-shown):invalid {
      border-color: var(--color-invalid);
    }
    
    
    /* Valid state */
    
    input:not(:placeholder-shown):valid {
      border-color: var(--color-valid);
    }
    <form>
      <input name="name" type="text" minlength="3" maxlength="20" required placeholder="test min/max length input" />
    </form>
    Login or Signup to reply.
  2. Surely. Instead of setting the required attribute prematurely, you can mark items with something (a required class in this case) and program the events you want to trigger the adding of the required attribute (blur in this case):

    function myBlur() {
        this.setAttribute("required", null);
    }
    
    function myFocus() {
        this.removeAttribute("required");
    }
    
    for (let item of document.getElementsByClassName("required")) {
        item.addEventListener("blur", myBlur);
        item.addEventListener("focus", myFocus);
    }
    input:invalid {
      border: 10px solid red;
    }
    <form>
      <input class="required" placeholder="you must type something" />
    </form>

    In the example above I’m adding the required attribute on blur and removing it on focus, so it will not yell at users if they are removing the content while the item is being focused, but will be complaining whenever the item loses focus while not having a value.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search