Search code examples
htmlcsslabelfloating

How do I fix floating CSS label always being active showing 'invalid input' in my form?


I am trying to get my survey form questions to have floating labels that are still visible when the user is inputting data, and after adding email validation with an error message, the second question is broken. It shows as being always invalid, even with no input.

I have tried changing the CSS selector to an adjacent sibling combinator, but while this gets my label in the correct place initially, it breaks the specific input[type="email"]:invalid ~.question-label styling.

Here is the HTML:

<div class="form-option">
    <input type="email" id="email" class="question-answer" placeholder=" " required>
    <span class="bar"></span>
    <label class="question-label" id="email-label">Email<span class="asterisk"> *</span></label>
    <div class="requirements">
      Must be a valid email address
    </div>
</div>

Here is the relevant CSS:

.question-answer:focus ~.question-label, .question-answer:valid ~.question-label {
    top: -16px;
    font-size: 14px;
     color: #4285f4;
}
input[type="email"]:valid + label {
  opacity: 0;
}
.requirements {
  padding-top: 5px;
  font-style: italic;
  color: red;
  opacity: 0;
  display: none;
}
input[type="email"]:invalid {
    background-color: pink;
    transition: ease .25s;
}

input[type="email"]:invalid ~.question-label {
    top: -16px;
    font-size: 14px;
    color: red;
}
input[type="email"]:invalid:focus ~.requirements {
    opacity: 100;
    display: block;
}

There is a full Codepen here: https://codepen.io/Pixel123/pen/NzByep if the issue needs clarification.

I am wanting for the labels to be in one starting position, then to move up and resize once focused on, and turn blue once a valid email has been entered (this part works). If input is not a valid email, the div that states Must be a valid email address becomes visible.

As it stands, the input highlighting that should only show on invalid emails is always on, and highlighting the field when there is no input.


Solution

  • You'll need to use the :empty selector and set the background color to your chosen color; in the case of your pen this is white:

    .question-answer:empty {
      background-color: #FFF !important;
    }
    

    To cover the case where the label isn't transitioning like the rest; follow the same idea by using :not:empty where you set the input[type="email"]:invalid.


    Below is a working example; take note of the use of :empty on question-answer.

        .question-answer:focus ~.question-label, .question-answer:valid ~.question-label {
            top: -16px;
            font-size: 14px;
             color: #4285f4;
        }
        .question-answer:empty {
          background-color: #FFF !important;
        }
        input[type="email"]:valid + label {
          opacity: 0;
        }
        .requirements {
          padding-top: 5px;
          font-style: italic;
          color: red;
          opacity: 0;
          display: none;
        }
        input[type="email"]:invalid {
            background-color: pink;
            transition: ease .25s;
        }
    
        input[type="email"]:invalid:not:empty ~.question-label {
          top: -16px;
          font-size: 14px;
          color: red;
        }
        input[type="email"]:invalid:focus ~.requirements {
            opacity: 100;
            display: block;
        }
        <div class="form-option">
            <input type="email" id="email" class="question-answer" placeholder=" " required>
            <span class="bar"></span>
            <label class="question-label" id="email-label">Email<span class="asterisk"> *</span></label>
            <div class="requirements">
              Must be a valid email address
            </div>
        </div>