18

When I type the last number in, the first number goes inside the text-box (it disappears), it's adding one extra space.

enter image description here

enter image description here

After I click outside the text-box it looks good which I need during typing last character. enter image description here

  #number_text {
        padding-left: 9px;
        letter-spacing: 31px;
        border: 0;
        background-image: linear-gradient(to right, #e1e1e1 70%, rgba(255, 255, 255, 0) 0%);
        background-position: left bottom;
        background-size: 38px 1px;
        background-repeat: repeat-x;
        width: 220px;
        box-sizing: border-box;
        outline:none;
    }
<input type="text" id="number_text" maxlength="6"  pattern="\d{6}" value="1234" >

Help me to get out from this issues. Thanks

Javier Heisecke
  • 1,162
  • 1
  • 11
  • 28
Jignesh Panchal
  • 1,037
  • 11
  • 29
  • Sorry, but I don't understand the issue? – evolutionxbox Jan 17 '20 at 11:43
  • 1
    Looks like you need to make it a bit wider to handle the carot for the last character. – freedomn-m Jan 17 '20 at 11:44
  • @evolutionxbox took me a minute or two... the snippet does demonstrate the issue nicely - it's an input box with large letter-spacing. Click at the end of the input and type - it stops at 6, but `1` (first character) gets lost to the left of the input (scrolled out with overflow hidden). – freedomn-m Jan 17 '20 at 11:45
  • Same issue, but no answer that works in current Chrome (at least) : https://stackoverflow.com/questions/8961045/prevent-horizontal-scrolling-of-a-text-input – freedomn-m Jan 17 '20 at 11:50
  • I'd suggest using 6 separate `input` controls and moving the caret between them as a character is typed/deleted. Otherwise you're *always* going to have alignment issues between browsers/font sizes/zoom levels etc – Rory McCrossan Jan 17 '20 at 11:58
  • You might be able to get something to work with a wider input and css `background-repeat: space no-repeat;` but I tried a bit and it seems to stretch the placeholder so they no longer line up neatly. See https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat – freedomn-m Jan 17 '20 at 11:58
  • Alternatively, use an pre-built image (jpg/png) instead of css linear-gradient. But you'll likely get more issues with font sizes as advised above. – freedomn-m Jan 17 '20 at 12:00
  • Look here: https://stackoverflow.com/questions/38746130/limit-the-number-of-characters-in-a-separate-input-field-for-each-character – Alex Jan 29 '20 at 17:20
  • From what I understand, OP wants the digits to fit exactly on the bottom grey lines (look at the screenshots). His issue is that each character does not take its rightful place _while_ typing. – AniMir Feb 05 '20 at 11:16

8 Answers8

7

Add space for another number and clip the input using clip-path

#number_text {
  padding-left: 9px;
  letter-spacing: 31px;
  border: 0;
  background: 
    repeating-linear-gradient(to right, #e1e1e1 0 26px, transparent 26px 38px)
    bottom/100% 1px no-repeat;
  width: 260px;
  clip-path:polygon(0 0, calc(100% - 38px) 0, calc(100% - 38px) 100%, 0 100%);
  box-sizing: border-box;
  outline: none;
}
<input type="text" id="number_text" maxlength="6" pattern="\d{6}" value="1234">

Or without clip-path by reducing the background-size:

#number_text {
  padding-left: 9px;
  letter-spacing: 31px;
  border: 0;
  background: 
    repeating-linear-gradient(to right, #e1e1e1 0 26px, transparent 26px 38px)
    bottom left/calc(100% - 38px) 1px no-repeat;
  width: 260px;
  box-sizing: border-box;
  outline: none;
}
<input type="text" id="number_text" maxlength="6" pattern="\d{6}" value="1234">
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
3

Use this code. its nicely work

var container = document.getElementsByClassName("wrap")[0];
    container.onkeyup = function(e) {
        var target = e.srcElement;
        var maxLength = parseInt(target.attributes["maxlength"].value, 6);
        var myLength = target.value.length;
        if (myLength >= maxLength) {
            var next = target;
            while (next = next.nextElementSibling) {
                if (next == null)
                    break;
                if (next.tagName.toLowerCase() == "input") {
                    next.focus();
                    break;
                }
            }
        }
     else if (myLength <= maxLength)
      {
        prev=target.previousElementSibling;
         while (prev = prev) {
            if (prev == null)
                break;
            if (prev.tagName.toLowerCase() == "input") {
                prev.focus();
                break;
            }
        }
      }

    }
.wrap input {
            border-top: 0;
            border-left: 0;
            border-right: 0;
            border-bottom: 1px solid #000;
            width: 3%;
            display: inline-block;
            outline: 0;
            text-align: center;
        }
<div class="wrap">
        <input type="text" maxlength="1" />
        <input type="text" maxlength="1" />
        <input type="text" maxlength="1" />
        <input type="text" maxlength="1" />
        <input type="text" maxlength="1" />
        <input type="text" maxlength="1" />
    </div>
Sreeraj_ms
  • 541
  • 3
  • 13
Rameez Bukhari
  • 486
  • 2
  • 6
  • Thanks for such a good solution but it's make problem when using backspace to remove number after entering numbers. This problem will not happening in single input text. – Jignesh Panchal Jan 17 '20 at 12:55
  • add this code to else part of if in `else if (myLength <= maxLength) { prev=target.previousElementSibling; while (prev = prev) { if (prev == null) break; if (prev.tagName.toLowerCase() == "input") { prev.focus(); break; } } }` – Sreeraj_ms Jan 17 '20 at 12:59
  • @jigneshpanchalmj if your issue resolved so make my answer correct. – Rameez Bukhari Jan 17 '20 at 14:31
  • 1
    Although it fixes the placeholder issue, this solution requires *substantial* more work to make it usable. eg click on 3rd input and type - goes in 3rd (might be what you want) - then click in 2nd and type a different number twice - goes in 2nd but 3rd input gets ignored. So left-cursor back - cursor is ignored (or more specifically reverted). Maybe that's ok, just doesn't feel very nice as-is. – freedomn-m Jan 17 '20 at 15:04
  • `parseInt(target.attributes["maxlength"].value, 6);` "6" isn't a default, it's the base to convert the int – freedomn-m Jan 17 '20 at 15:07
  • yes it's work fine but can we do same things with single input field? – Jignesh Panchal Jan 21 '20 at 06:41
2

Try to add this script bellow the input-field:

<script>
  var oInput = document.getElementById('number_text');
  oInput.onkeypress = function(ev) {
    setTimeout(function() {
        if( oInput.value.length > 5 ) {
            oInput.setSelectionRange(0,0);
            oInput.blur();
        }
    }, 0);
  }
</script>

This one forces your input-cursor to the beginning of the input after the 6th character was entered. I also added a blur() to the field so the cursor-jump to the beginning won't stick out.

The timeout is also needed. Without it the entered character will be inserted at the beginning. More about timeout: Is setTimeout a good solution to do async functions with javascript?

Jura Herber
  • 131
  • 8
1

You can deal with it by adding a blur() event of js onkeyup of input box:

myFunction=()=>{
if(document.getElementById("number_text").value.length===6)
document.getElementById("number_text").blur();
}
 #number_text {
        padding-left: 9px;
        letter-spacing: 31px;
        border: 0;
        background-image: linear-gradient(to right, #e1e1e1 70%, rgba(255, 255, 255, 0) 0%);
        background-position: left bottom;
        background-size: 38px 1px;
        background-repeat: repeat-x;
        width: 220px;
        box-sizing: border-box;
        outline:none;
        overflow-y:hidden;
        overflow-x:hidden;
    }
<input type="text" id="number_text" maxlength="6"  pattern="\d{6}" value="1234" onkeyup="myFunction()" >
<br/>
0

Please change on css below (it will works)

padding-left: 14px;

to

padding-left: 5px;
rajesh
  • 209
  • 1
  • 8
0

So I like Temani Afif's answer about using the clipping mask. Think it's great. I wanted to propose another solution (a little less elegant). I used Firefox to also test this problem, and clicking outside the text area (losing focus) does not make the 1st digit re-appear or the string go back to normal in the text input there.

I believe the issue is the letter spacing css attribute you set:letter-spacing: 31px;, and the fact that I believe this would apply to the "blinking" caret that most browsers have. Using Chrome, it seems to remove this when it loses focus, while Firefox retains this even after losing focus.

The 1st solution was to use manually call the blur() function to make the input lose focus. This works in Chrome (using a Self-Executing Anonymous Function):

<input type="text" id="number_text" maxlength="6" onkeyup="(function()
    {
      var x = document.getElementById('number_text');
      let value = x.value
      if (value.length >= 6){
        x.blur()
        return false
      }
    })();"
 pattern="\d{6}" value="1234" >

or even as a Defined Function called by the number_text input like so:

<script>
 handleMaxInput = function(){
  var x = document.getElementById('number_text');
  let value = x.value
  if (value.length >= 6){
    x.blur()
    return false
  }
};
</script>

<input ... id='number_text' ... onkeyup="handleMaxInput()" ... >

You will notice a slight delay in Chrome, but calling this in Firefox will not resolve the issue.

We can essentially force this same behavior in Firefox. After some playing around, I figured that Chrome was refreshing/recalculating the letter spacing on a blur. My play session showed that you could force Firefox to recalculate this value programmatically:

  1. Change the inline style of the input's letter-spacing attribute to a different value (as we cannot edit a CSS class of number_text programmatically without much effort, such as re-writing the entire style tag in the style section of a document).
  2. Remove the Class number_text from the input.
    • 1 and 2 are interchangeable, you need Firefox to fallback to only the inline style you set, without having the class attributes saved 'in memory'.
  3. Remove the inline-style and reapply the number_text CSS class. This will force the browser to recalculate the letter-seperation as we need it to.

In code, it would look like the following JavaScript function:

handleMaxInput = function(){
        var x = document.getElementById('number_text');
        let value = x.value
        if (value.length >= 6){ // if the input is 6 or more characters
              x.classList.remove('number_text') // remove the class
              x.style.letterSpacing = '0px' // reset the spacing
              setTimeout(function() { // set time to let browser refresh updates
                  x.classList.add('number_text') // Re-add class after browser refresh
                  setTimeout(function() { // Remove inline-style after more reculculations
                      x.style.removeProperty('letter-spacing') // Remove inline style to let class styles apply
                      x.blur // optional, will force input field to lose focus. Else comment out to avoid that.
              }, (1)); // waits 1 millisecond
          }, (1)); // waits 1 millisecond
        }
    }

It will have that same flicker in Firefox as with Chrome, and all shall be well.

Note: The timeout functions are to give the browser time to refresh, and actually update what we need.

Note: You can choose to call .blur() in the function to make the textbox lose focus, or omit that and they will still be in the input field without the error with the digits.

Hope this helps your conceptual understanding, as well as solving the issue. Some other individuals gave good solutions that avoid the whole flicker thing, and work in both Firefox and Chrome!

Tumo Masire
  • 422
  • 5
  • 10
0

It looks like a common UI issue I've encountered before.

I bet it only fails on some platforms as well (this is the nature of this particular bug.)

On some, but not all, platforms, a spacing character is used to indicate the caret.

On some, but not all, platforms, this character is non-spacing, but overlaying, on the next, not the last, character. Hence if there is no next character will be filled with the space until input is done.

In both these cases the display will act in this manner.

This is a case where the best solution is the simplest solution, accommodating for this common system quirk, not the solution that forces it to behave the way you want it to as some people suggested. This is less likely to introduce bugs, and more likely to work on all platforms.

The solution is give a little bit of spare room at the end of the entry for displaying this.

Increase "width" to 230 or 240 and you should be good.

Further, you could even better accommodate non-standard systems, especially accessibility systems with alternative fonts or size attributes, by simply detecting the width by entering full width spaces in the area, adding a quarter width space at the end, measuring them, then deleting them, or simply rigging it to overwrite the full width spaces as the user types (or otherwise enters data, don't presume it's a keyboard or even something that enters one character at a time.)

0

$(document).on('keyup','#numberinput',function(){
      var aa = $(this).val();

      var aa = aa.substring(1);

      if(aa.length > 5)
      {
       $('#numberinput').val(aa);
      }
     });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" name="" id="numberinput">
Marmik Patel
  • 192
  • 2
  • 12