Last updated on

The :optional pseudo class targets inputs (including <select>s) that are not specifically set as required (do not have the required attribute).

This can be useful when you want to give optional fields a specific look, maybe slightly less visible than required ones.

Syntax

input[type=text]:optional {
  border: 1px solid #eee;
}

Demo

In the following demo, optional field (“Name”, “Gender” and “Continent”) have their opacity lowered to 40% so users can immediately know what are the required fields. In this case, “Email”. When hovered, an optional input will see the opacity go back to 100%.

The optional works on all type of form elements: text inputs of all types, radio buttons, checkboxes, and selects.

<form>
  <p>
    <label for="first-name"><span class="fontawesome-user"></span> Name</label>
    <input type="text" id="name" placeholder="John Doe" />
  </p>
  <p>
    <label for="email"><span class="fontawesome-envelope"></span> Email</label>
    <input type="text" id="email" placeholder="john.doe@gmail.com" required />
  </p>
  <p>
    <input type="radio" name="gender" id="man" /> <label class="inline" for="man">Man</label>
    <input type="radio" name="gender" id="woman" /> <label class="inline" for="woman">Woman</label>
  </p>
  <p>
    <label for="continent"><span class="fontawesome-globe"></span> Continent</label>
    <select id="continent">
      <option value="0">Continent</option>
      <option value="1">North America</option>
      <option value="2">South America</option>
      <option value="3">Europe</option>
      <option value="4">Africa</option>
      <option value="5">Asia</option>
      <option value="6">Oceania</option>
    </select>
  </p>
  <p>
    <input type="submit" value="Sign up" />
  </p>
</form>
* {
  box-sizing: border-box;
}

:optional {
  opacity: 0.4;
  transition: .2s;
}

:optional:hover {
  opacity: 1;
}

form {
  width: 100%;
  max-width: 400px;
  margin: 20px auto;
  background: #EFEFEF;
  padding: 1em;
}

label {
  display: block;
  margin-bottom: 5px;
  color: #666;
}

.inline {
  display: inline;
  margin-right: 1em;
}

input[type="text"] {
  padding: 5px;
  width: 100%;
  border: 1px solid silver;
}

input[type=submit] {
  background: deepskyblue;
  color: white;
  padding:10px 0;
  border-color: rgba(0,0,0,.1);
  font-weight: bold;
  opacity: 1;
  width: 100%;
}

select {
  width: 100%;
  border: 1px solid silver;
  padding: 5px;
}

@import url(http://weloveiconfonts.com/api/?family=fontawesome);

/* fontawesome */
[class*="fontawesome-"]:before {
  font-family: 'FontAwesome', sans-serif;
}

Note: you cannot know with CSS only that a label is associated with an optional field, unless in the label comes after the input (and you use a sibling combinator), which is rare and usually not a good idea. Perhaps in the future parent selectors can help with this.

Related Properties

Browser Support

Chrome Safari Firefox Opera IE Android iOS
10+ 5+ 4+ 10+ 10+ Any 5+

Note that :optional isn’t the exact oposite of :not(:required) because the latter will match all types of elements while :optional is restricted to the form elements.