How to Create a Shake Animation for Invalid Input in CSS

Adel Benyahia
4 min readDec 22, 2022

Learn how to add an eye-catching animation to text input that contain invalid values, such as non-word characters, improperly formatted email or phone number…

Photo by Sigmund from Unsplash

We will use two approach in this step by step article:

  1. HTML and CSS
  2. React and JavaScript

We have different pure CSS animations to choose from (shake1, shake2…,shake7)

@keyframes shake1 {
0% {
margin-left: 0rem;
}
25% {
margin-left: 0.5rem;
}
75% {
margin-left: -0.5rem;
}
100% {
margin-left: 0rem;
}
}

@keyframes shake2 {
0% {
transform: translate(1px, 1px) rotate(0deg);
}
10% {
transform: translate(-1px, -2px) rotate(-1deg);
}
20% {
transform: translate(-3px, 0px) rotate(1deg);
}
30% {
transform: translate(3px, 2px) rotate(0deg);
}
40% {
transform: translate(1px, -1px) rotate(1deg);
}
50% {
transform: translate(-1px, 2px) rotate(-1deg);
}
60% {
transform: translate(-3px, 1px) rotate(0deg);
}
70% {
transform: translate(3px, 1px) rotate(-1deg);
}
80% {
transform: translate(-1px, -1px) rotate(1deg);
}
90% {
transform: translate(1px, 2px) rotate(0deg);
}
100% {
transform: translate(1px, -2px) rotate(-1deg);
}
}

@keyframes shake3 {
0% {
transform: translate(1px, 1px) rotate(0deg);
}
20% {
transform: translate(-3px, 0px) rotate(1deg);
}
40% {
transform: translate(1px, -1px) rotate(1deg);
}
60% {
transform: translate(-3px, 1px) rotate(0deg);
}
90% {
transform: translate(1px, 2px) rotate(0deg);
}
100% {
transform: translate(1px, -2px) rotate(-1deg);
}
}

@keyframes shake4 {
0%,
100% {
transform: translateX(0);
}
10%,
30%,
50%,
70%,
90% {
transform: translateX(-10px);
}
20%,
40%,
60%,
80% {
transform: translateX(10px);
}
}

@keyframes shake5 {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(5deg);
}
50% {
transform: rotate(0eg);
}
75% {
transform: rotate(-5deg);
}
100% {
transform: rotate(0deg);
}
}

@keyframes shake6 {
0% {
transform: translateX(0);
}
25% {
transform: translateX(5px);
}
50% {
transform: translateX(-5px);
}
75% {
transform: translateX(5px);
}
100% {
transform: translateX(0);
}
}

@keyframes shake7 {
0% {
transform: translate(0, 0) rotate(0deg);
}
25% {
transform: translate(5px, 5px) rotate(5deg);
}
50% {
transform: translate(0, 0) rotate(0eg);
}
75% {
transform: translate(-5px, 5px) rotate(-5deg);
}
100% {
transform: translate(0, 0) rotate(0deg);
}
}

1. HTML and CSS

For this approach we will use only HTML and CSS

. HTML

<input placeholder="Type a word" pattern="[A-Za-z]*" />

As you can see we use the magic pattern attribute, with the Regex value “[A-Za-z]*”, this will be true only if the input value contain letters.

Spaces, numbers and special characters are not accepted

The pattern Attribute

The input pattern attribute specifies a regular expression that the input field's value is checked against, when the form is submitted.

The pattern attribute works with the following input types: text, date, search, url, tel, email, and password.

Tip: Use the global title attribute to describe the pattern to help the user.

Tip: Learn more about regular expressions in our JavaScript tutorial.

If the pattern don’t match (not a valid word in our case) then the input will return invalid.

We will use The :invalid CSS pseudo-class to style the input like this

input:invalid {
animation: shake3 0.4s ease-in-out 0s 2;
color: #ff9494;
border: 2px solid #ff9494;
border-radius: 5px;
}

As you can see, if the input is invalid then this CSS pseudo-class in applied, with the animation

animation: shake3 0.4s ease-in-out 0s 2;

You can change the “shake3” to “shake1…shake7” to try different animations, the same for the duration and the type.

The color “#ff9494” will be applied for the text and the border of the input

2. React and JavaScript

This approach is different,

We have a CSS class “error” that will be applied for in valid input

.error {
animation: shake3 0.4s ease-in-out 0s 2;
color: #ff9494;
border: 2px solid #ff9494;
border-radius: 5px;
}

We will use useState to manage the input value

    const [inputValue, setInputValue] = useState("");
...
<input
placeholder="Type a word"
className={IsValidSingleWord(inputValue) ? null : "error"}
value={inputValue}
onChange={changeHandler}
/>

As you can see, we will use the JavaScript function “IsValidSingleWord” to apply or not the class “error” to the input style

  const pattern = /^[A-Za-z]+$/;
const IsValidSingleWord = (word) => {
return pattern.test(word) || word.length === 0;
};
const changeHandler = (e) => {
setInputValue(e.target.value);
};

The IsValidSingleWord will return true only when we have a valid word.

The “|| word.length === 0;” ,is true when the input is empty.

Every time the input change, the inputValue state will change forcing the app to re-render ( it’s React …), and the isValidSingleWord function is executed.

Full source code

--

--

Adel Benyahia

Web application developer (HTML │ CSS │ JS | ReactJS | NextJS | NestJS | MERN)