Here's a solution that creates one text box with underscores under each character (try deleting and writing a different number in the input field):
input { border: none; width: 10.5ch; background: repeating-linear-gradient(90deg, dimgrey 0, dimgrey 1ch, transparent 0, transparent 1.5ch) 0 100%/100% 2px no-repeat; color: dimgrey; font: 5ch consolas, monospace; letter-spacing: .5ch; } input:focus { outline: none; color: dodgerblue; }
<input maxlength='7' value='0123456'/>
The ch block is used here, whose width is equal to the width of the character 0 . It also assumes that the font in the input field is monospaced, so that all characters have the same width.
Thus, the width for each character is always 1ch . The gap between characters is taken equal to .5ch . This is the value we set for letter-spacing . width of input - the number of characters multiplied by the sum between the width of the letter ( 1ch ) and the width of the gap ( .5ch ). So 7*(1ch + .5ch) = 7*1.5ch = 10.5ch .
We remove the actual border input , and we set the fake, using repeating-linear-gradient . The dash ( dimgrey ) goes from 0 to 1ch , and the space ( transparent ) starts immediately after the dash and goes to 1.5ch .
It is attached to the left and bottom of the input - this is the background-position component ( 0% horizontally and 100% vertically).
It spreads across the entire input horizontally ( 100% ) and 2px tall is a component of background-size background .
The Sass code that this CSS generates:
$char-w: 1ch; $gap: .5*$char-w; $n-char: 7; $in-w: $n-char*($char-w + $gap); input { border: none; width: $in-w; background: repeating-linear-gradient(90deg, dimgrey 0, dimgrey $char-w, transparent 0, transparent $char-w + $gap) 0 100%/100% 2px no-repeat; font: 5ch consolas, monospace; letter-spacing: $gap; &:focus { outline: none; color: dodgerblue; } }
You can customize the gap and other things here .
source share