dboy
dboy

Reputation: 33

Split input into separate boxes

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

Answers (1)

Kostas Minaidis
Kostas Minaidis

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

Related Questions