The pseudoclasses :empty, :valid and :invalid not working as I expected

I am trying to give an input element different border types depending on whether the input element is either empty, invalid or valid. My code is as follows:

input[type="number"]:invalid{
    border: thick solid red;
}
input[type="number"]:empty{
    border: thin solid black;
}


input[type="number"]:valid{
    border: medium solid darkgreen;
}

The styling works only if I omit the empty pseudoclass, in which case the system treats an empty input element as invalid.
Does anyone have any idea what I am doing wrong?

A number type input cant be empty? (No, that’s not serious.)
The syntax appears correct, other than the missing space between the selector and the open bracket…

What does the HTML element look like? Cause… valid/invalid implies you’ve got a test running on the field…

Thanks for the reply.
This is the HTML code:

<label for="HourlyRate">Hourly Rate *</label>
                    <input type="number" id="HourlyRate" name="HourlyRate" placeholder="Rate: between 20 and 50" min="20" max="50" required>
                    <label for ="HoursWorked">Hours Worked *</label>
                    <input type="number" id="HoursWorked" name="HoursWorked" placeholder="Hours Worked: between 5 and 60" min="5" max="60" required>

I want the data in the HourlyRate element to be between 20 and 50 inclusive. Any values outside of this range should render the element invalid - which it does.
Same applies to the HoursWorked.
Any idea how to convey to the user that an input element has had no data entered into it?
Or is it the case that a number type input is always invalid until valid data is entered.
This is almost like the Catholic theology about original sin.

Wrap your HTML code in backticks (```) so that the forum doesnt try to interpret it.

I’ve done it for you this time, @apanthonypowell, but for future reference, do remember that advice. :slight_smile:

1 Like

So here’s how I make your code work:

input[type="number"]:invalid {
    border: thick solid red;
}

input[type="number"]:valid {
    border: medium solid darkgreen;
}
input[type="number"]:placeholder-shown {
    border: thin solid black;
}

Rather than checking empty, check and see if your field’s placeholder is showing. If so, make the border black. If not, evaluate valid/invalid. (Note that the order of these is important - the field is both invalid and showing the placeholder while the field is empty, so you want the black to override the red.)

1 Like

Inputs are always :empty because their content is provided via their attributes. They do not have content as such and therefore are always :empty. They are not much use for form validation in this way.

The placeholder-shown method posted by @m_hutley above should do what you want.:slight_smile: