12

I want to create a html5 input that looks like the iOS enter Pin (on the lock screen).... with 4 input boxes.

How do i achieve this?

enter image description here

I tried the following:

1) Created a normal input box.

2) Removed its borders.

3) Placed the above image as the background of the input box.

4) And added some letter spacing.

Problem is: As i type the first 3 characters, it fits in the boxes:

enter image description here

But when i type the 4th character, the characters move towards the left and hence it appears as below:

enter image description here

What can I do to fix this ?

Any other better approach ??

EDIT:

Ok based on the below answers, I modified the approach to have 4 input boxes. And on keyup event for each input box, I change the focus to next input box.

This works well on browser. But does not work on the device (iPhone 5). What is the problem ?

It is a Sencha Touch app packaged using Cordova.

SOLVED:

Need to disable <preference name="KeyboardDisplayRequiresUserAction" value="false" />

isherwood
  • 58,414
  • 16
  • 114
  • 157
senchaDev
  • 587
  • 2
  • 6
  • 19

8 Answers8

10

Instead of images, have 4 input boxes. Fiddle here: http://jsfiddle.net/JLyn9/2/

<input type="password" maxlength=1 id="1" onkeyup="moveOnMax(this,'a')" />
<input type="password" maxlength=1 id="a" onkeyup="moveOnMax(this,'b')" />
<input type="password" maxlength=1 id="b" onkeyup="moveOnMax(this,'c')" />
<input type="password" maxlength=1 id="c" />

moveOnMax =function (field, nextFieldID) {
    if (field.value.length == 1) {
        document.getElementById(nextFieldID).focus();
    }
}

PS the JS function can be optimized.

EDIT/WARNING: This is not a solution to this problem. Please look at the other answers

stackErr
  • 4,130
  • 3
  • 24
  • 48
  • thanks. i am using sencha touch to create the input components.. so my code is a bit different. but I got the idea.. and i have implemented in a similar way. thanks for the approach – senchaDev Nov 21 '13 at 08:27
  • 2
    @stackErr What if user want to use backspace to delete pin and move to previous field – EmptyData Feb 03 '15 at 07:37
  • This works awfully. You should try something else. I also see the issue @EmptyData points out. – Santiago Baigorria Jul 22 '15 at 14:54
  • @EmptyData Hi, I would like to get feedback from you about my solution to this problem, please check it out https://stackoverflow.com/a/73847672/17948008. – M NARESH Sep 25 '22 at 20:34
4

Instead of using background-image for this purpose, use four input boxes with their type set to password, and than use jQuery to achieve some more user friendliness, if you don't need that functionality of auto focusing to next field you can simply omit the script out and achieve your style..

Demo

input[type=password] {
    padding: 10px;
    border: 1px solid #ddd;
    width: 50px;
    height: 50px;
    text-align: center;
    font-size: 30px;
}

jQuery (Optional for auto focus functionality)

$("input").keyup(function() {
    if($(this).val().length >= 1) {
      var input_flds = $(this).closest('form').find(':input');
      input_flds.eq(input_flds.index(this) + 1).focus();
    }
});
Mr. Alien
  • 153,751
  • 34
  • 298
  • 278
4

No need for jQuery, much cleaner IMO.

HTML

<form id="ios">
    <input type="password" maxlength="1" />
    <input type="password" maxlength="1"/>
    <input type="password" maxlength="1"/>
    <input type="password" maxlength="1"/>
</form>   

CSS

form#ios input[type=password]{
    height: 50px;
    width: 40px;
    text-align: center;
    font-size: 2em;
    border: 1px solid #000;
} 

Demo

http://jsfiddle.net/jerryhuangme/e9yhr/

Community
  • 1
  • 1
JerryHuang.me
  • 1,790
  • 1
  • 11
  • 21
  • I've not used jQuery to style elements :) that option is used for auto focus – Mr. Alien Nov 21 '13 at 07:08
  • @Mr.Alien, ah. I should have RTFM. Just saw $("input").keyup(function() and was scratching my head. That's a nice snippet of UI design there. Good job. – JerryHuang.me Nov 21 '13 at 07:13
2

To keep the style clean, I would suggest you to create 4 input boxes.

Write a small script to focus the next input box when user enters character in the current input box.

aBhijit
  • 5,261
  • 10
  • 36
  • 56
1

$("input[name*=pin]").keyup(function(e) {
  if($(this).val().length == 1) {
    $(this).attr('type', 'password');
    var input_fields = $(this).closest('form').find('input[name*=pin]');
    input_fields.eq(input_fields.index(this) + 1).focus();
  }
  if (e.keyCode==8 && e.currentTarget.name !== 'pin01') {
    $(this).attr('type', 'number');
    var input_fields = $(this).closest('form').find('input[name*=pin]');
    input_fields.eq( input_fields.index(this) - 1 ).attr('type', 'number').focus(); 
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<form action="" class="form-pin">
  <input type="number" maxlength="1" name="pin01" class="input-pin" pattern="\d*" />
  <input type="number" maxlength="1" name="pin02" class="input-pin" pattern="\d*" />
  <input type="number" maxlength="1" name="pin03" class="input-pin" pattern="\d*" />
  <input type="number" maxlength="1" name="pin04" class="input-pin" pattern="\d*" />
</form>
eozzy
  • 66,048
  • 104
  • 272
  • 428
0
 <input type="tel" maxlength="1" tabindex="1" class="display-otp-box" data-key="otp1">
 <input type="tel" maxlength="1" tabindex="2" class="display-otp-box" data-key="otp2">
 <input type="tel" maxlength="1" tabindex="3" class="display-otp-box" data-key="otp3">
 <input type="tel" maxlength="1" tabindex="4" class="display-otp-box" data-key="otp4">


$('.display-otp-box').on('keyup', function (e) {
  var key = event.keyCode || event.charCode;
        
  /* for backspace, focus will move to the previous box */ 
  if( key === 8 || key === 46 ){
     $(this).prev('input').focus();
     return;
  }
  $(this).next('input').focus();
 });
  • type="tel" on the input will make sure the numeric keypad appears when using on the phone
  • next input will be focused automatically with the help of tabindex.
Parita Patel
  • 82
  • 2
  • 8
0

I have seen all the answers but none solves the issue when backspace is clicked,

to tackle that here is my solution,

HTML:

        <input class="input" type="text" id="input-1" maxlength=1 data-id="1" />
        <input class="input" type="text" id="input-2" maxlength=1 data-id="2" />
        <input class="input" type="text" id="input-3" maxlength=1 data-id="3" />
        <input class="input" type="text" id="input-4" maxlength=1 data-id="4" />

CSS:

.input {
    padding: 0.8rem;
    border: 1px solid #ddd;
    width: 50px;
    height: 50px;
    text-align: center;
    font-size: 30px;
    margin-left: 1rem;
  }

Javascript:

const loginInputs = document.querySelectorAll(".input");

loginInputs.forEach((el) => {
  el.addEventListener("keyup", (e) => {
    const id = +e.target.dataset.id;
    if (e.key === "Backspace") {
      if (id === 1) return;
      const prevEl = document.getElementById(`input-${id - 1}`);
      prevEl.focus();
    } else {
      if (id === 4) return;
      const nextEl = document.getElementById(`input-${id + 1}`);
      nextEl.focus();
    }
  });
});
M NARESH
  • 142
  • 1
  • 7
0

No need for JS. This solution covers back-spacing, copy/pasting etc, just using html and CSS.

If the numbers in the input field move towards the right when typing the 4th number, it is likely due to the default behavior of some web browsers that display the characters entered in the input field as asterisks or bullets. This behavior can cause the input text to appear shifted to the right.

To resolve this issue, you can modify the element to use a fixed-width font. This ensures that each character occupies the same amount of space, preventing the shifting effect. You can apply a CSS style to the input field to achieve this:

<input type="text" id="pin-input" maxlength="4" style="font-family: monospace;">

full html component:

        <div id="pin-container">
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <label for="pin-number" class="sr-only">PIN</label>
          <input type="password" name="pin-number" id="pin-number" maxlength="4" style="font-family: monospace;">
        </div>

<style>
  #pin-container {
    display: inline-block;
    position: relative;
  }
  #pin-container div {
    background-color: #F2F2F2;
    border: 2px solid #222;
    border-radius: 7px;
    float: left;
    height: 3em;
    margin-right: 0.25em;
    width: 3em;
  }
  #pin-number {
    background-color: transparent;
    border: none;
    bottom: 1.1em;
    /* font-family: monospace; <-- here or inline html */
    font-size: 1.9em;
    left: 0.8em;
    letter-spacing: 1.64em;
    outline: none;
    position: absolute;
  }
</style>