Here is a handy tip. Unfortunately, it's not possible to directly style validation popups using CSS.
// A solution to disable native validation UI with `noValidate`
// Perform evaluation on form submit and prevent submission if necessary
const form = document.querySelector('form')
form.noValidate = true
form.onsubmit = evt => {
if (!form.checkValidity()) {
evt.preventDefault()
}
}
// Loop through fields in the form
for (const field of form.querySelectorAll('input, textarea, select')) {
// Add error container
field.insertAdjacentHTML('afterend', '<div class="error"></div>')
// Display error message on `invalid` event
field.oninvalid = () => {
field.classList.add('invalid')
field.nextSibling.textContent = field.validationMessage
// Remove invalid state & error message on `input` event, trigger validation check
const inputHandler = () => {
field.oninput = null
field.nextSibling.textContent = ''
field.classList.remove('invalid')
field.checkValidity()
}
field.oninput = inputHandler
}
}
/* Custom global styles */
html {
height: 100%;
}
body {
font-family: sans-serif;
font-weight: 300;
font-size: 20px;
background: linear-gradient(to top, #e0e7ef, #eef2f7);
min-height: 100%;
color: #798594;
line-height: 1.6;
}
/* Custom form styles */
form {
background: #f8fafb;
padding: 3em 1em;
border-radius: 3px;
box-shadow: 0 0.1em 0.4em #b7ccde;
max-width: 15em;
margin: 2em auto;
}
button, input, textarea, select {
font: inherit;
color: inherit;
padding: 0.4em 0.6em;
border: 1px solid #ccc;
border-radius: 4px;
width: 100%;
box-sizing: border-box;
margin-bottom: 0.5em;
}
button {
cursor: pointer;
background-color: #e9f1ff;
color: #7e93b7;
}
input {
display: block;
position: relative;
z-index: 1;
}
input::placeholder {
color: #bbb;
}
/* Styling for errors */
.invalid {
box-shadow: 0 0.15em 0.15em -0.1em rgba(4, 4, 4, 0.1);
}
.error {
display: none;
margin-bottom: 0.5rem;
margin-top: calc(-0.5rem - 4px);
margin-left: 2px;
margin-right: 2px;
padding: calc(0.5rem + 4px) 0.6rem;
background-color: #ffefeb;
color: #b75a41;
border: 1px solid #e6917a;
border-radius: 0 0 4px 4px;
animation: show-error 0.3s;
font-size: 0.8em;
}
.invalid + .error {
display: block;
}
@keyframes show-error {
from {
transform: translateY(-2em) scaleY(0.2);
}
to {
transform: none;
}
}
<form>
<input
type="number"
placeholder="Enter 42"
min="42"
max="42"
required>
<input
type="email"
placeholder="Enter your email"
required>
<button type="submit">Register</button>
</form>