JSFiddle - React, Tailwind, and code Playground
HTML
<div>
<span class="input-mask">999-99-9999</span><input maxlength="10" type="text" value="" />
</div>
CSS
input { margin:0; outline: none; border-radius: 4px; height:16px; border: 2px solid black; padding: 4px; font-weight:bold; font-size: 14px; width:81px; text-align: left; font-family: Consolas, Monaco, monospace; }
.mask-literal { color: black; }
JavaScript
var spn = document.getElementsByTagName("span")[0],
inp = document.getElementsByTagName("input")[0],
cs = window.getComputedStyle(inp, null),
i = cs.length,
txt = "textContent" in document.body ? "textContent" : "innerText",
ignore
while (i--) {
var s = cs[i];
// Copy all styles from <input> to <span> and <button>
if (s && s != "cssText" && s.slice(0,6) != "column" && s != "-ms-wrap-margin")
spn.style.setProperty(s, cs.getPropertyValue(s), null);
}
// wrap each character in <span class="input-mask"> with another <span>
spn.innerHTML = spn.innerHTML.replace(/./g, "<span>$&</span>")
.replace(/<span>\/<\/span>/g, '<span class="mask-literal">/</span>');
// Presto's & Gecko's <input> elements are `display:inline`
spn.style.display = 'inline-block';
spn.style.position = 'absolute';
spn.style.borderColor = "transparent";
spn.style.backgroundColor = "transparent";
spn.style.color = "lightgray";
spn.style["-webkit-text-fill-color"] = null;
spn.style.pointerEvents = "none";
spn.contentEditable = true;
spn.onfocus = function () {
setCaret(inp, getCaret(spn));
}
inp.onkeypress = function() {
var evt = arguments[0] || window.event,
chr = String.fromCharCode(evt.which || evt.keyCode),
pos = getCaret(inp);
if (!evt.which && !evt.keyCode)
return;
if (pos !== 2 && pos !== 5) {
if (isNaN(chr))
return false;
else if (pos === 1 || pos === 4) {
window.setTimeout(function () {
insertTextWithoutDestroyingUndo(inp, "/");
}, 0);
}
}
else
return chr === "/";
}
inp.onkeydown = function () {
var pos,
evt = arguments[0] || window.event,
key = evt.which || evt.keyCode,
len = inp.value.length;
/* fix for IE */
ignorePC = true;
pos = getCaret(inp);
ignorePC = false;
if ((key === 46 && pos != len -1) || key === 8 && pos != len)
...