Reputation: 33
I am looking to separate an input into individual character/digit boxes, like this photo
Ideally, entering a digit would take you to the next input box and each one would be highlighted separately with the active border. I can use a combination of styling and Javascript to accomplish this.
Any insight would be really helpful! Thanks in advance.
Upvotes: 2
Views: 7077
Reputation: 5516
Here's one way to implement this pattern:
HTML:
<div class="digits">
<input type="text" maxlength="1" name="digit1" />
<input type="text" maxlength="1" name="digit2" />
<input type="text" maxlength="1" name="digit3" />
<input type="text" maxlength="1" name="digit4" />
</div>
CSS:
input {
font-size: 2rem;
width: 1.5rem;
text-align: center;
}
input:focus {
border: 2px solid yellowgreen;
outline: none;
}
JAVASCRIPT:
// Listen on the 'input' event inside the .digits area:
document.querySelector(".digits").addEventListener("input", function(e){
// Exclude non-numeric characters from input:
e.target.value = e.target.value.replace(/[^0-9]/g,'');
// If the input value is filled and there is a neighbouring element that is input, then focus on that element:
if ( e.target.value !== "" && e.target.nextElementSibling && e.target.nextElementSibling.nodeName === "INPUT" ){
e.target.nextElementSibling.focus();
}
});
2) In case you want the input values to be updated when already filled:
<div class="digits">
<input type="text" name="digit1" />
<input type="text" name="digit2" />
<input type="text" name="digit3" />
<input type="text" name="digit4" />
</div>
document.querySelector(".digits").addEventListener("input", function(e){
e.target.value = e.data.replace(/[^0-9]/g,'');
if ( e.target.value !== "" && e.target.nextElementSibling && e.target.nextElementSibling.nodeName === "INPUT" ){
e.target.nextElementSibling.focus();
}
});
document.querySelector("input").focus();
document.querySelector(".digits").addEventListener("input", function({ target, data }){
// Exclude non-numeric characters (if a value has been entered)
data && ( target.value = data.replace(/[^0-9]/g,'') );
const hasValue = target.value !== "";
const hasSibling = target.nextElementSibling;
const hasSiblingInput = hasSibling && target.nextElementSibling.nodeName === "INPUT";
if ( hasValue && hasSiblingInput ){
target.nextElementSibling.focus();
}
});
input {
font-size: 3rem;
width: 2.6rem;
border: 2px solid #aaa;
text-align: center;
box-shadow: 0 0 8px rgba(0,0,0,0.25);
}
input:focus {
border: 2px solid yellowgreen;
outline: none;
}
/* DECORATION */
input:focus {
animation-name: zoom;
animation-duration: 200ms;
}
@keyframes zoom {
from {
}
to {
transform: scale(2);
}
}
body {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-color: lightgray;
}
.digits {
padding: 20px;
display: inline-block;
}
<div class="digits">
<input type="text" name="digit1" />
<input type="text" name="digit2" />
<input type="text" name="digit3" />
<input type="text" name="digit4" />
<input type="text" name="digit5" />
</div>
Codepen (Contains some extra validation and effects)
Upvotes: 6