<div class="container">
  <p>
    Input should be a number. A letter will make it :invalid. Also a value that is in range (1-10) will also match just like <code>:in-range</code> would. The styles applied using <code>:in-range</code> would override the styles applied using <code>:valid</code> if they come after them in the style sheet. Try adding <code>:in-range</code> styles in the CSS to see this in action.
  </p>
  <input type="number" min="1" max="10" value="8">
  <p>
    Input type email. Email is optional, so it is valid even with no input. As you start typing, it will turn red and be considered :invalid until the input you're typing matches the pattern of a valid email address.
  </p>
  <input type="email">
  <p>
    Input type email. Email is required, so it will be invalid while it is empty and will validate only when you type in a value that matches the pattern of a valid email address.
  </p>
  <input type="email" required>
  <p>
    Input type URL. If the value you enter does not match the pattern of a URL, it will apply the invalid styles.
  </p>
  <input type="url">
</div>
body {
  color: #555;
  font-size: 1.2em;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

hr {
  margin: 50px 0;
}

.container {
  margin: 40px auto;
  max-width: 700px;
}

input {
  display: block;
  width: 50%;
  height: 2em;
}

input[type="number"] {
  width: auto;
}

input:valid {
  background-color: lightgreen;
}

input:invalid {
  background-color: tomato;
}
/*input[type="number"]:valid {
background-color: orange;
}
input[type="number"]:in-range {
background-color: yellow;
}*/

input:valid:focus {
  outline: 0;
  border: none;
  box-shadow: 0 0 3px 6px rgba(0, 200, 0, 0.3);
}