CSS Selectors Related to Form Control
Tags: formvalidation, css, selector
Published: 2020-03-22 04:39:25

<blockquote>
Nowadays, we tend to use JavaScript to validate the form. Then adding some classes to help us style the input elements. In some cases, we probably no need to create extra classes because there are already some CSS selectors that can help us do the job. In this article, I will introduce some CSS selectors related to form control which you might not know before.
</blockquote>

## Agenda
  * [Form Related CSS Selectors](#agenda-1)
  * [:require & :placeholder-shown](#agenda-2)
  * [:out-of-range](#agenda-3)
  * [:invalid](#agenda-4)
  * [:default](#agenda-5)
  * [:read-only](#agenda-6)
  * [Browser Support](#agenda-7)

### Form Related CSS Selectors <a name="agenda-1"></a>
This image is coming from the [State of CSS 2019](https://2019.stateofcss.com/). Some of the CSS selectors related to form control had not used by many developers.

![css-selectors](https://2019.stateofcss.com/images/captures/units-and-selectors_form-controls.png)



### :require & :placeholder-shown <a name="agenda-2"></a>
![required](https://i.imgur.com/jTlkfAB.gif)

The first example is `:required`. Because we can't use `Pseudo-elements` for the input element, Therefore I add an extra div after the input element to display the message.  
```html
<label>
  <span>Name</span>
  <input type="text" name="name" placeholder="your name" required />
  <div></div>
</label>
```

Then we can use `:required` to add some style for the input which is must fill up.    
```css
input:required + div::before {
  content: "(required)";
  color: red;
}
```

If we want to hide the warning message after the user fills up the input, we can use `:placeholder-shown` to do the trick.  
```css
input:required + div::before {
  display: none;
}
input:placeholder-shown + div::before {
  display: block;
}
```


### :out-of-range <a name="agenda-3"></a>
![out-of-range](https://i.imgur.com/Z3B4Yzb.gif)

If we have set a range for the input, then we can use `:out-of-range` to alert the user when the input value is not within the limit.  
```html
<label>
  <span>Years of Experience</span>
  <input type="number" min="0" max="100" />
  <div></div>
</label>
```

```css
input:out-of-range + div::before {
  content: "(out-of-range)";
  color: red;
}
```

### :invalid <a name="agenda-4"></a>
![invalid](https://i.imgur.com/U2NnuFK.gif)  

If there was some error on the content that the user provides, we might want to notify the user that the form is not completed yet. Here we can apply `:invalid` to display the result.

```html
<form>
  <label>
    <span>Name</span>
    <input type="text" name="name" placeholder="your name" required />
    <div></div>
  </label>
  <button type="submit"></button>
</form>
```
```css
button:before {
  content: "Ready to Submit";
}
form:invalid > button {
  background: darkgray;
}
form:invalid > button:before {
  content: "Not Ready";
}
```

### :default <a name="agenda-5"></a>
![default](https://i.imgur.com/abe2zXp.png)

Sometimes we will set a default option for the checkbox or radio. It's good to let the user know this option is checked by default. We can use `:default` to add extra style for that.

```html
<div>
  <span>Fields</span>
  <label>
    <input type="checkbox" value="fe" checked />
    Front-End Developer
    <div></div>
  </label>
  <label>
    <input type="checkbox" value="be" />
    Back-End Developer
    <div></div>
  </label>
</div>
```
```css
input:default + div::before {
  content: "(default)";
  color: red;
}
```

### :read-only <a name="agenda-6"></a>
![read-only](https://i.imgur.com/zeYcFXT.png)

When the user is editing the form, we might not allow them to edit certain columns (ex. user id). So we can use `:read-only` display a different style to identity that.

```html
<label>
  <span>Referred by</span>
  <input type="text" value="oahehc@gamil.com" readonly />
  <div></div>
</label>
```
```css
input:read-only + div::before {
  content: "(read-only)";
  color: red;
}
```

Here is an example to display all the above scenarios.  
{% codepen https://codepen.io/oahehc/pen/MWwqeRo %}

### Browser Support <a name="agenda-7"></a>
Here is the status of the browser support for all those `Pseudo-classes`.  (2020-03-22)  

![:required](https://i.imgur.com/VAEZok8.png)
![:placeholder-shown](https://i.imgur.com/PMaSXhU.png)
![:out-of-range](https://i.imgur.com/5D300eu.png)
![:invalid](https://i.imgur.com/lDuMkXO.png)
![:default](https://i.imgur.com/U8ubNw1.png)
![:read-only](https://i.imgur.com/KxqyFzw.png)


---

## Conclusion
Frankly, handling form validation through JavaScript can provide maximum flexibility, and we can easily create extra classes for style the input elements base.   

If the use case is simple and we can implement the form validation by using HTML attributes. Then using CSS selectors to style the input elements will be a good solution.  

The code will be easier to read because we have standard syntax. And HTML now already have enough attributes to help us validate the input for most of the use case.  
![Constraint Validation HTML Input Attributes](https://i.imgur.com/cWojGkS.png)

The downside of using HTML attributes to do the form validation is the style will be inconsistent in different browsers.  
![browser-validate-all](https://i.imgur.com/mIOn7av.png)

--

## Reference
  * [CSS pseudo-class](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)
  * [form-controls selectors](https://2019.stateofcss.com/units-and-selectors/#form-controls)
  * [HTML Input Attributes](https://www.w3schools.com/html/html_form_attributes.asp)
  * [Form Validation](https://www.w3schools.com/js/js_validation.asp)