Table of Contents
Introduction :
User engagement can be significantly increased by including entertaining and interactive elements in web design. The Naughty Submit Button is a playful element that responds to user clicks by moving. You can give your web forms a special twist of surprise and difficulty by using this button.
The complete source code and line-by-line explanations will be provided to ensure that you can follow along easily as we take you through ten simple steps to create this CSS button effect. This tutorial will provide you a deeper understanding of creating dynamic CSS button animations and effects in addition to a workable, playful button.
Step 1: HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Naughty Login form</title>
<link rel="shortcut icon" href="./final upscale.png" type="image/x-icon">
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap"
/>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="container">
<h2>Naughty Submit Button</h2>
<input type="text" placeholder="Username" id="username" />
<input type="password" placeholder="Password" id="password" />
<button id="submit">Submit</button>
<p id="message-ref">Signed Up Successfully!</p>
</div>
<script src="./index.js"></script>
</body>
</html>
HTML Explanation for CSS button:
<meta charset="UTF-8">
: This ensures the webpage correctly displays characters from different languages. Necessary for global compatibility.
<link rel="stylesheet" href="...">
: Links the Google Poppins font and external CSS file (index.css). Important to define the appearance of your elements.
<script src="index.js">
: Loads the JavaScript file (index.js) to handle the form’s behavior, such as button movement and validation.
Inputs and Button: These are straightforward—<input>
tags collect user data (username and password), and the <button>
is the submit button.
Success Message (<p id="message-ref">
): Hidden initially, this displays a success message after the form is filled correctly.
Step 2 : CSS Button Code
CSS Code:
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
background-color: #202020;
}
.container {
width: 31.25em;
background-color: #f8f8f8;
padding: 1.4em 3.75em;
position: absolute;
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
border-radius: 0.7em;
box-shadow: 0 1em 4em rgba(212, 234, 255, 0.2);
}
h2{
text-align: center;
font-size: 32px;
margin-bottom: 30px;
color: lightblack;
}
input,
#submit {
border: none;
outline: none;
display: block;
}
input {
width: 100%;
background-color: transparent;
margin-bottom: 2em;
font-size: 20px;
padding: 1em 0 0.5em 0.5em;
border-bottom: 2px solid #202020;
}
#submit {
position: relative;
left: 0;
font-size: 1.1em;
width: 7em;
background-color: #10fc57;
color: white;
padding: 0.8em 0;
margin-top: 2em;
border-radius: 0.3em;
}
#message-ref {
font-size: 0.9em;
margin-top: 1.5em;
color: #34bd34;
visibility: hidden;
}
CSS Explanation for Naughty Submit Button:
* { padding: 0; margin: 0; ... }
: Resets default padding and margins, and sets box-sizing for consistent element sizing. Ensures layout behaves predictably.
Container Styling: The container is centered using position: absolute
and transform: translate(-50%, -50%)
, which ensures it’s perfectly in the middle of the page.
Input and Submit Button Styling: These elements are styled for modern appearance, removing borders, adding padding, and customizing background and text colors.
Button and Input Validation Feedback: Input fields change colors based on their validity (red for invalid, green for valid).
Success Message (#message-ref
): Styled to be hidden initially (using visibility: hidden
), and will appear when the user successfully submits the form.
STEP 3 : JavaScript For CSS Button
JavaScript code:
let usernameRef = document.getElementById("username");
let passwordRef = document.getElementById("password");
let submitBtn = document.getElementById("submit");
let messageRef = document.getElementById("message-ref");
let isUsernameValid = () => {
/* Username should be contain more than 3 characters. Should begin with alphabetic character Can contain numbers */
const usernameRegex = /^[a-zA-Z][a-zA-Z0-9]{3,32}/gi;
return usernameRegex.test(usernameRef.value);
};
let isPasswordValid = () => {
/* Password should be atleast 8 characters long. Should contain atleast 1 number, 1 special symbol , 1 lower case and 1 upper case */
const passwordRegex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/gm;
return passwordRegex.test(passwordRef.value);
};
usernameRef.addEventListener("input", () => {
if (!isUsernameValid()) {
messageRef.style.visibility = "hidden";
usernameRef.style.cssText =
"border-color: #fe2e2e; background-color: #ffc2c2";
} else {
usernameRef.style.cssText =
"border-color: #34bd34; background-color: #c2ffc2";
}
});
passwordRef.addEventListener("input", () => {
if (!isPasswordValid()) {
messageRef.style.visibility = "hidden";
passwordRef.style.cssText =
"border-color: #fe2e2e; background-color: #ffc2c2";
} else {
passwordRef.style.cssText =
"border-color: #34bd34; background-color: #c2ffc2";
}
});
submitBtn.addEventListener("mouseover", () => {
//If either password or username is invalid then do this..
if (!isUsernameValid() || !isPasswordValid()) {
//Get the current position of submit btn
let containerRect = document
.querySelector(".container")
.getBoundingClientRect();
let submitRect = submitBtn.getBoundingClientRect();
let offset = submitRect.left - containerRect.left;
console.log(offset);
//If the button is on the left hand side.. move it to the the right hand side
if (offset <= 100) {
submitBtn.style.transform = "translateX(16.25em)";
}
//Vice versa
else {
submitBtn.style.transform = "translateX(0)";
}
}
});
submitBtn.addEventListener("click", () => {
messageRef.style.visibility = "visible";
});
JavaScript Explanation
let usernameRef = document.getElementById("username");
let passwordRef = document.getElementById("password");
let submitBtn = document.getElementById("submit");
let messageRef = document.getElementById("message-ref");
Variable Declarations
usernameRef
: This variable stores a reference to the username input field by usingdocument.getElementById("username")
. This allows you to manipulate the element directly.passwordRef
: Similarly, this variable references the password input field, allowing for validation and interaction.submitBtn
: This variable holds the reference to the submit button, enabling you to add event listeners to it for interactions.messageRef
: This variable points to the paragraph element that displays the success message. It starts off hidden and is manipulated based on user input.
let isUsernameValid = () => {
const usernameRegex = /^[a-zA-Z][a-zA-Z0-9]{3,32}/gi;
return usernameRegex.test(usernameRef.value);
};
Username Validation Function
isUsernameValid
: This is an arrow function that checks if the username input is valid.const usernameRegex
: A regular expression is defined to validate the username:^
: Asserts the start of the string.[a-zA-Z]
: The first character must be an alphabet (either lowercase or uppercase).[a-zA-Z0-9]{3,32}
: The username can then contain alphanumeric characters, and must be at least 4 characters long (1 alphabet + 3 alphanumeric characters), and can be up to 32 characters in total.gi
: Flags for global search and case-insensitive matching.
.test(usernameRef.value)
: This method checks if the current value of the username input matches the regex pattern, returningtrue
if it’s valid andfalse
otherwise.
let isPasswordValid = () => {
const passwordRegex = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/gm;
return passwordRegex.test(passwordRef.value);
};
Password Validation Function
isPasswordValid
: This arrow function validates the password input.const passwordRegex
: A regular expression that enforces the password rules:(?=.*\d)
: At least one digit must be present.(?=.*[a-z])
: At least one lowercase letter must be present.(?=.*[A-Z])
: At least one uppercase letter must be present..{8,}
: The total length must be at least 8 characters.gm
: Flags for global search and multiline matching.
.test(passwordRef.value)
: Similar to the username validation, it checks the current password value against the regex.
usernameRef.addEventListener("input", () => {
if (!isUsernameValid()) {
messageRef.style.visibility = "hidden";
usernameRef.style.cssText =
"border-color: #fe2e2e; background-color: #ffc2c2";
} else {
usernameRef.style.cssText =
"border-color: #34bd34; background-color: #c2ffc2";
}
});
Username Input Event Listener
addEventListener("input", ...)
: This event listener triggers every time the user types in the username input field.- Inside the callback function:
if (!isUsernameValid())
: Checks if the username is invalid.- If invalid, the success message (
messageRef
) is hidden, and the input field’s border color is set to red (#fe2e2e
) with a light red background (#ffc2c2
).
- If invalid, the success message (
else
: If the username is valid, the input field is styled with a green border (#34bd34
) and a light green background (#c2ffc2
).
- Inside the callback function:
passwordRef.addEventListener("input", () => {
if (!isPasswordValid()) {
messageRef.style.visibility = "hidden";
passwordRef.style.cssText =
"border-color: #fe2e2e; background-color: #ffc2c2";
} else {
passwordRef.style.cssText =
"border-color: #34bd34; background-color: #c2ffc2";
}
});
Password Input Event Listener
- Similar to the username input listener, this one triggers on every input change in the password field.
- It performs validation through
isPasswordValid()
:- If invalid, it hides the success message and applies red styling.
- If valid, it applies green styling.
- It performs validation through
submitBtn.addEventListener("mouseover", () => {
if (!isUsernameValid() || !isPasswordValid()) {
let containerRect = document
.querySelector(".container")
.getBoundingClientRect();
let submitRect = submitBtn.getBoundingClientRect();
let offset = submitRect.left - containerRect.left;
if (offset <= 100) {
submitBtn.style.transform = "translateX(16.25em)";
} else {
submitBtn.style.transform = "translateX(0)";
}
}
});
Submit Button Mouseover Event Listener
addEventListener("mouseover", ...)
: This event triggers when the user hovers over the submit button.- Inside the callback:
if (!isUsernameValid() || !isPasswordValid())
: Checks if either the username or password is invalid.- If so, it calculates the position of the submit button relative to its container:
getBoundingClientRect()
: Retrieves the size and position of the button and container in the viewport.offset
: The difference in the left position of the button and the container.
- If the button is on the left side (offset ≤ 100), it moves the button to the right using
transform: translateX(16.25em)
. - If the button is already on the right, it resets its position with
transform: translateX(0)
.
- If so, it calculates the position of the submit button relative to its container:
- Inside the callback:
submitBtn.addEventListener("click", () => {
messageRef.style.visibility = "visible";
});
Submit Button Click Event Listener
addEventListener("click", ...)
: This event triggers when the user clicks the submit button.messageRef.style.visibility = "visible"
: When the button is clicked, this makes the success message visible, indicating successful signup. It should ideally be shown only when both inputs are valid, but this implementation shows it on click regardless of input validity.
Step 4 : Testing live preview

Play Around (live preview):
Step 5 : Download
