<section>
<div class="container">
<h1 class="title">输入验证码</h1>
<form id="otp-form">
<input type="text" class="otp-input" maxlength="1">
<input type="text" class="otp-input" maxlength="1">
<input type="text" class="otp-input" maxlength="1">
<input type="text" class="otp-input" maxlength="1">
<input type="text" class="otp-input" maxlength="1">
</form>
<button id="verify-btn">点击验证</button>
</div>
</section>
HTML
格式化
支持Emmet,输入 p 后按 Tab键试试吧!
<head> ... </head>
<body>
</body>
CSS
格式化
@import url("https://fonts.googleapis.com/css2?family=Inter&display=swap");
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: Inter;
}
body {
width: 100%;
background: #1a2226;
color: white;
}
section {
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.container {
border-radius: 12px;
background-color: rgb(19, 25, 28);
width: 90%;
max-width: 500px;
padding: 50px 20px;
text-align: center;
}
.title {
font-size: 25px;
margin-bottom: 30px;
}
#otp-form {
width: 100%;
display: flex;
gap: 20px;
align-items: center;
justify-content: center;
}
#otp-form input {
border: none;
background-color: #121517;
color: white;
font-size: 32px;
text-align: center;
padding: 10px;
width: 100%;
max-width: 70px;
height: 70px;
border-radius: 4px;
outline: 2px solid rgb(66, 66, 66);
}
#otp-form input:focus-visible {
outline: 2px solid royalblue;
}
#otp-form input.filled {
outline: 2px solid rgb(7, 192, 99);
}
#verify-btn {
cursor: pointer;
display: inline-block;
margin-top: 30px;
background: royalblue;
color: white;
padding: 7px 10px;
border-radius: 4px;
font-size: 16px;
border: none;
}
JS
格式化
const form = document.querySelector("#otp-form");
const inputs = document.querySelectorAll(".otp-input");
const verifyBtn = document.querySelector("#verify-btn");
const isAllInputFilled = () => {
return Array.from(inputs).every((item) => item.value);
};
const getOtpText = () => {
let text = "";
inputs.forEach((input) => {
text += input.value;
});
return text;
};
const verifyOTP = () => {
if (isAllInputFilled()) {
const text = getOtpText();
alert(`Your OTP is "${text}". OTP is correct`);
}
};
const toggleFilledClass = (field) => {
if (field.value) {
field.classList.add("filled");
} else {
field.classList.remove("filled");
}
};
form.addEventListener("input", (e) => {
const target = e.target;
const value = target.value;
console.log({ target, value });
toggleFilledClass(target);
if (target.nextElementSibling) {
target.nextElementSibling.focus();
}
verifyOTP();
});
inputs.forEach((input, currentIndex) => {
// fill check
toggleFilledClass(input);
// paste event
input.addEventListener("paste", (e) => {
e.preventDefault();
const text = e.clipboardData.getData("text");
console.log(text);
inputs.forEach((item, index) => {
if (index >= currentIndex && text[index - currentIndex]) {
item.focus();
item.value = text[index - currentIndex] || "";
toggleFilledClass(item);
verifyOTP();
}
});
});
// backspace event
input.addEventListener("keydown", (e) => {
if (e.keyCode === 8) {
e.preventDefault();
input.value = "";
// console.log(input.value);
toggleFilledClass(input);
if (input.previousElementSibling) {
input.previousElementSibling.focus();
}
} else {
if (input.value && input.nextElementSibling) {
input.nextElementSibling.focus();
}
}
});
});
verifyBtn.addEventListener("click", () => {
verifyOTP();
});