如何分区输入字段以在屏幕上显示为单独的输入字段?

IT技术 javascript html css twitter-bootstrap
2021-02-18 10:46:32

看图:

在此处输入图片说明

我想要设计类似于图像中的内容,其中用户需要输入 4 位数字一次性密码 (OTP)。现在我已经通过 4 个单独的输入实现了这一点,然后在 javascript 中组合值:

<input type="text" class="form-control" placeholder="0" maxlength="1"  />
<input type="text" class="form-control" placeholder="0" maxlength="1" />
<input type="text" class="form-control" placeholder="0" maxlength="1" />
<input type="text" class="form-control" placeholder="0" maxlength="1" />

我不确定这是否是正确的方法。我认为必须有一些样式选项,通过这些选项,一个输入文本框会像图像中一样显示为分区。是否可以使用引导程序?如何设置一个输入控件的样式以显示为输入的分区字段?

6个回答

您不必保留 4 个单独的字段;

首先你应该调整字符间距,然后调整底部的边框样式......

#partitioned {
  padding-left: 15px;
  letter-spacing: 42px;
  border: 0;
  background-image: linear-gradient(to left, black 70%, rgba(255, 255, 255, 0) 0%);
  background-position: bottom;
  background-size: 50px 1px;
  background-repeat: repeat-x;
  background-position-x: 35px;
  width: 220px;
}
<input id="partitioned" type="text" maxlength="4" />

--编辑以修复 4 个字符丑陋的 5 个下划线--

var obj = document.getElementById('partitioned');
obj.addEventListener('keydown', stopCarret); 
obj.addEventListener('keyup', stopCarret); 

function stopCarret() {
	if (obj.value.length > 3){
		setCaretPosition(obj, 3);
	}
}

function setCaretPosition(elem, caretPos) {
    if(elem != null) {
        if(elem.createTextRange) {
            var range = elem.createTextRange();
            range.move('character', caretPos);
            range.select();
        }
        else {
            if(elem.selectionStart) {
                elem.focus();
                elem.setSelectionRange(caretPos, caretPos);
            }
            else
                elem.focus();
        }
    }
}
#partitioned {
  padding-left: 15px;
  letter-spacing: 42px;
  border: 0;
  background-image: linear-gradient(to left, black 70%, rgba(255, 255, 255, 0) 0%);
  background-position: bottom;
  background-size: 50px 1px;
  background-repeat: repeat-x;
  background-position-x: 35px;
  width: 220px;
  min-width: 220px;
}

#divInner{
  left: 0;
  position: sticky;
}

#divOuter{
  width: 190px; 
  overflow: hidden;
}
<div id="divOuter">
	<div id="divInner">
		<input id="partitioned" type="text" maxlength="4" />
	</div>
</div>

我认为这可以是一个起点...希望这会有所帮助...

如果我们没有给出最大长度 4,我将面临字符对齐的问题,在输入几位数字后,数字在右侧,它没有对齐输入字段的破折号的中心
2021-04-24 10:46:32
是的,你是对的,这似乎是限制:( 作为旁注,实际上有 5 个分区线。对于这个丑陋的地方,你可以将输入字段放在一个 div 中,并将该 div 放在另一个......内部 div 必须是粘性的,外部 div 必须隐藏溢出......
2021-04-28 10:46:32
单击时要删除蓝色矩形边框吗?您可以将outline:nonecss 规则添加#partitioned样式中
2021-05-01 10:46:32
那么信用卡号或日期字段呢?
2021-05-03 10:46:32
@UfukOnder 你能帮我设置 6 的文本长度吗?
2021-05-10 10:46:32

我知道这个问题很老了。当我试图为我的项目实现同样的目标时,我偶然发现了这一点。

我找不到我需要的东西。所以我用这里的想法自己做了一个

您可以将其与任意数量的字符一起使用,并且只要所有输入字段都在divwith,就不需要在 javascript 中进行更改id="otp"


这是一个预览:

在此处输入图片说明


看看这里的代码

function OTPInput() {
  const inputs = document.querySelectorAll('#otp > *[id]');
  for (let i = 0; i < inputs.length; i++) {
    inputs[i].addEventListener('keydown', function(event) {
      if (event.key === "Backspace") {
        inputs[i].value = '';
        if (i !== 0)
          inputs[i - 1].focus();
      } else {
        if (i === inputs.length - 1 && inputs[i].value !== '') {
          return true;
        } else if (event.keyCode > 47 && event.keyCode < 58) {
          inputs[i].value = event.key;
          if (i !== inputs.length - 1)
            inputs[i + 1].focus();
          event.preventDefault();
        } else if (event.keyCode > 64 && event.keyCode < 91) {
          inputs[i].value = String.fromCharCode(event.keyCode);
          if (i !== inputs.length - 1)
            inputs[i + 1].focus();
          event.preventDefault();
        }
      }
    });
  }
}
OTPInput();
@import url('https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css');
.form-control {
  -webkit-transition: none;
  transition: none;
  width: 32px;
  height: 32px;
  text-align: center
}

.form-control:focus {
  color: #3F4254;
  background-color: #ffffff;
  border-color: #884377;
  outline: 0;
}

.form-control.form-control-solid {
  background-color: #F3F6F9;
  border-color: #F3F6F9;
  color: #3F4254;
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.form-control.form-control-solid:active,
.form-control.form-control-solid.active,
.form-control.form-control-solid:focus,
.form-control.form-control-solid.focus {
  background-color: #EBEDF3;
  border-color: #EBEDF3;
  color: #3F4254;
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
<div class="mb-6 text-center">
  <div id="otp" class="flex justify-center">
    <input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="first" maxlength="1" />
    <input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="second" maxlength="1" />
    <input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="third" maxlength="1" />
    <input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="fourth" maxlength="1" />
    <input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="fifth" maxlength="1" />
    <input class="m-2 text-center form-control form-control-solid rounded focus:border-blue-400 focus:shadow-outline" type="text" id="sixth" maxlength="1" />
  </div>
</div>

@mihun 你能解释一下如何在输入字段中只添加数字吗?. OTP 屏幕只需要数字。
2021-04-22 10:46:32
我发现在最后一个输入字段上退格时,它实际上清除了最后一个输入以及倒数第二个输入。简单的解决方法是检查最后一个输入并if (i == inputs.length - 1)在退格的情况下以不同的方式处理它
2021-04-25 10:46:32
应该这样做。其余的答案并不好。感谢您的功能片段:D
2021-05-11 10:46:32

这对我有用,无需任何额外的 javascript 代码。

#partitioned {
  padding-left: 15px;
  letter-spacing: 42px;
  border: 0;
  background-image: linear-gradient(to left, black 70%, rgba(255, 255, 255, 0) 0%);
  background-position: bottom;
  background-size: 50px 1px;
  background-repeat: repeat-x;
  background-position-x: 35px;
  width: 220px;
  min-width: 220px;
}

#divInner{
  left: 0;
  position: sticky;
}

#divOuter{
  width: 190px; 
  overflow: hidden;
}
<div id="divOuter">
  <div id="divInner">
<input id="partitioned" type="text" maxlength="4" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*)\./g, '$1');"  onKeyPress="if(this.value.length==4) return false;"/>
  </div>
</div>

它的工作原理,我需要知道要更改什么才能使其成为 6 位输入字段?
2021-05-01 10:46:32
没有 javascript 的惊人解决方案。@TanujK 对 6 位 otp 的评论也值得称赞......
2021-05-13 10:46:32
@MrZid 要使其成为 6 位输入字段,您必须进行以下更改。1.在CSS中将#partitioned的min-width和width更改为305px 2.在CSS中将#divOuter的宽度更改为290px 3.并更改maxlength = "6" and onKeyPress="if(this.value.length== 6) 返回假;" 在 HTML 中
2021-05-14 10:46:32
它也接受字母表......应该只接受数字,因为它是一个 otp
2021-05-14 10:46:32
单击时要删除蓝色矩形边框吗?您可以将outline:nonecss 规则添加#partitioned样式中
2021-05-15 10:46:32

希望此解决方案对您有所帮助。如果需要,您可以输入元素中删除onfocus事件

<body>
  <head>
    <style>
      input[type=number] {
          height: 45px;
          width: 45px;
          font-size: 25px;
          text-align: center;
          border: 1px solid #000000;
      }
      input[type=number]::-webkit-inner-spin-button,
      input[type=number]::-webkit-outer-spin-button {
        -webkit-appearance: none;
        margin: 0;
      }
    </style>
    <script>
      function getCodeBoxElement(index) {
        return document.getElementById('codeBox' + index);
      }
      function onKeyUpEvent(index, event) {
        const eventCode = event.which || event.keyCode;
        if (getCodeBoxElement(index).value.length === 1) {
          if (index !== 4) {
            getCodeBoxElement(index+ 1).focus();
          } else {
            getCodeBoxElement(index).blur();
            // Submit code
            console.log('submit code ');
          }
        }
        if (eventCode === 8 && index !== 1) {
          getCodeBoxElement(index - 1).focus();
        }
      }
      function onFocusEvent(index) {
        for (item = 1; item < index; item++) {
          const currentElement = getCodeBoxElement(item);
          if (!currentElement.value) {
              currentElement.focus();
              break;
          }
        }
      }
    </script>
  </head>
  <body>
    <form>
        <input id="codeBox1" type="number" maxlength="1" onkeyup="onKeyUpEvent(1, event)" onfocus="onFocusEvent(1)"/>
        <input id="codeBox2" type="number" maxlength="1" onkeyup="onKeyUpEvent(2, event)" onfocus="onFocusEvent(2)"/>
        <input id="codeBox3" type="number" maxlength="1" onkeyup="onKeyUpEvent(3, event)" onfocus="onFocusEvent(3)"/>
        <input id="codeBox4" type="number" maxlength="1" onkeyup="onKeyUpEvent(4, event)" onfocus="onFocusEvent(4)"/>
    </form>
  </body>
</body>

我只会保留这 4 个单独的字段方法,并向所有这些字段添加相同的事件处理程序,这将:

  1. 检查输入是否有效(在字符类中,你愿意接受)
  2. 检查您所在的字段,然后将焦点移到下一个字段,或单击“确定”按钮。

您甚至可以为此编写一些单独的 JS,然后重新使用它。