<div class="input-group">
<span class="input-group__cell">
<input class="input-group__input" type="number">
<span class="input-group__text"></span>
</span>
<span class="input-group__cell">
<input class="input-group__input" type="number">
<span class="input-group__text"></span>
</span>
<span class="input-group__cell">
<input class="input-group__input" type="number">
<span class="input-group__text"></span>
</span>
<span class="input-group__cell">
<input class="input-group__input" type="number">
<span class="input-group__text"></span>
</span>
</div>
* {
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
height: 100vh;
background-color: #00010a;
}
.input-group {
display: flex;
justify-content: center;
font-size: 2rem;
font-family: sans-serif;
}
.input-group__cell {
position: relative;
width: 1.75em;
flex-shrink: 0;
overflow: hidden;
}
.input-group__cell:not(:last-child) {
margin-right: 0.5em;
}
.input-group__input {
width: 100%;
margin: 0;
padding: 0.25em;
font: inherit;
text-align: center;
appearance: none;
background-color: transparent;
color: transparent;
border: 2px solid #202660;
border-radius: 5px;
appearance: textfield;
}
.input-group__input:focus {
border: 2px solid #9d2183;
outline: none;
}
.input-group__input::outer-spin-button,
.input-group__input::inner-spin-button {
appearance: none;
margin: 0;
}
.input-group__text {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
inset: 0;
color: #ccc;
pointer-events: none;
transform: translateY(100%);
}
.input-group__text.show {
transform: translateY(0);
transition: transform 350ms cubic-bezier(0.18, 0.89, 0.32, 1.28);
}
const nextFrame = (fn) => requestAnimationFrame(() => requestAnimationFrame(fn));
const inputGroup = document.querySelector('.input-group');
const inputCells = Array.from(
inputGroup.querySelectorAll('.input-group__cell'),
(el, index) => ({
index,
cell: el,
input: el.querySelector('.input-group__input'),
text: el.querySelector('.input-group__text'),
})
);
inputGroup.addEventListener('input', (event) => {
const cellGroup = inputCells.find(c => c.input === event.target);
const { index, text } = cellGroup;
const value = Number(event.data);
const hasValue = !Number.isNaN(value) && event.data !== null;
text.textContent = hasValue ? value : '';
event.target.value = hasValue ? value : '';
if (hasValue) {
text.classList.remove('show');
nextFrame(() => text.classList.add('show'));
if (index >= inputCells.length - 1) {
event.target.blur();
}
else {
inputCells[index + 1].input.focus();
}
}
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.