23

I have an input type password that only allow a six-digit number like this:

<fieldset>
  <label for="password-input">Enter New Pin</label>
  <input type="password" name="password" id="password-input" inputmode="numeric" minlength="6"
  maxlength="6" size="6" value="">
  <span class="hint">New pin must be 6 digit number only</span>
</fieldset>

It will show like this:

Default input appearance

How can I style it so it can look like the following?

Desired input appearance

5
  • We can't change the password masking character in input type password. We can do it for input type text but it has a security risk. Commented Oct 19, 2018 at 4:54
  • 15
    The fact that all of the answers below fail for at least one person should tell you not to attempt this. Commented Oct 19, 2018 at 7:53
  • similare question : stackoverflow.com/questions/49476209/… Commented Oct 19, 2018 at 8:22
  • 3
    I would go a different way. Use a single row, 6 cell table with background images and JavaScript/jQuery to process/mask/display. It will give you a lot more visual flexibility than trying to style a password input. It Is probably a lot more work but you can get everything to work and look exactly the way you want. Commented Oct 19, 2018 at 15:15
  • @SunKnight0 that would require to implement pasting from clipboard too for people with password managers. Commented Oct 19, 2018 at 17:38

5 Answers 5

25

Since you can't use the ::after pseudo-element on your input box, use it on fieldset (or if you can alter the HTML, add an element). Then give it a content value using underscores, and position the elements where you want them. Finally, add letter-spacing and width to your input box, and give it a :focus of outline: none to get rid of the blue box.

fieldset {
  color: #555;
  font-family: sans-serif;
  border: none;
  position: relative;
}

fieldset > * {
  display: block;
}

fieldset::after {
  content: "___  ___  ___  ___  ___  ___";
  display: block;
  position: absolute;
  top: 35px;
  white-space: pre;
}

label {
  font-size: 14px;
  margin-bottom: 6px;
}

input#password-input {
  position: relative;
  font-size: 16px;
  z-index: 2;
  border: none;
  background: transparent;
  width: 300px;
  text-indent: 9px;
  letter-spacing: 25.6px;
  font-family: Courier;
}

input#password-input:focus {
  outline: none;
}

span.hint {
  margin-top: 8px;
  font-size: 12px;
  font-style: italic;
}

span.hint::before {
  content: "* ";
}
<fieldset>
  <label for="password-input">Enter New Pin</label>
  <input type="password" name="password" id="password-input" inputmode="numeric" minlength="6" maxlength="6" size="6" value="">
  <span class="hint">New pin must be 6 digit number only</span>
</fieldset>

Sign up to request clarification or add additional context in comments.

6 Comments

@Ferrybig I set the font-family for input. Better?
@symlink the cursor is out of place for the last input
@blue That's expected; there's nothing that can be done about that really.
Width is wrong on Firefox - 5 characters get spread evenly over 6 underscores
Closer, but still off - by the 5th dot it's shifted to between the 5th and 6th underscores
|
14

Try this:

input {
  padding-left: 15px;
  letter-spacing: 39px;
  border: 0;
  background-image: linear-gradient(to left, black 70%, rgba(255, 255, 255, 0) 0%);
  background-position: bottom;
  background-size: 50px 3px;
  background-repeat: repeat-x;
  background-position-x: 35px;
  width: 280px;
  font-size: 30px;
}

input:focus {
  outline: none;
}
<fieldset>
  <label for="password-input">Enter New Pin</label>
  <input type="password" name="password" id="password-input" inputmode="numeric" minlength="6" maxlength="6" size="6" value="">
  <span class="hint">New pin must be 6 digit number only</span>
</fieldset>

11 Comments

the input font is too small, and when i enter the in put there is a blue border surrounding it, and when i enter the last character the input alignment become messy
This is actually the only answer that has the letter spacing right on Chromium on Ubuntu, but too bad there is a bug after the sixth character
@Ferrybig yes fixing that bug will update code shortly :)
@Ferrybig I hope you don't expect everyone to be able to test fonts for Ubuntu, because it's not as common as a Windows PC or even a OSX Mac . The font in my answer is Consolas and your machine doesn't recognize it. Change the font-family to something your machine recognizes.
Ubuntu is quite common, according to w3schools, more than 5% of their visitors use it: w3schools.com/browsers/browsers_os.asp and that considering most people had a time they avoided that website
|
7

You can place an element containing "the mask" behind the input and set the background color of input to transparent. But pay attention to the following details:

  • Use monospace font family so that the width of _ and is always the same.
  • End your font list with monospace so that OS can choose a fixed width font if all of the specified fonts are unavailable.
  • User agent could choose a different font family, size and line height for input elements. It can also choose a different size and line height for monospace fonts (e.g. medium size could be computed as 13px instead of the usual 16px and normal line height is often off by 1px for two different fonts having same size). So make sure you specify these properties explicitly.

Here is the result:

body {
  font-family: sans-serif;
}

fieldset label,
fieldset span {
  display: block;
  margin: .5em 0;
}

fieldset .input-wrapper {
  /* positioning */
  position: relative;
  /* font */
  font: 16px/1.5 monospace;
  letter-spacing: .5em;
  /* optional */
  background-color: #EEE;
}

fieldset .input-wrapper::before {
  /* positioning */
  position: absolute;
  /* masking */
  content: "______";
}

fieldset input {
  /* positioning */
  position: relative;
  /* font */
  font: inherit;
  letter-spacing: inherit;
  /* masking */
  background-color: transparent;
  /* reset */
  margin: 0;
  border: 0;
  padding: 0;
}
<fieldset>
  <label for="password-input">Enter New Pin</label>
  <div class="input-wrapper">
    <input type="password" name="password" id="password-input" inputmode="numeric" minlength="6" maxlength="6" value="">
  </div>
  <span class="hint">New pin must be 6 digit number only</span>
</fieldset>

2 Comments

Unlike the more-highly-upvoted answers, this one is spaced correctly in Firefox. Kinda makes me wonder if it looks funky in Chrome...
@Izkata I only checked in Chrome :)
7

Update

  • Added a <input type='number'> which can adjust the root font-size: 8px to 84px.

Relevant Points

  • The input is stripped of border, outline, and background.

  • Wrapped a label around the input as an overlay (technically it is an underlay? z-index: -1) which has a pseudo-class ::after with the content value of 6 underscores.

  • Both input and overlay must have the following properties:

      /* The values can anything as long as it is valid and are the same */
      letter-spacing: 10px;
      font-size: 1.2rem;
      font-weight: 900;
    
  • The overlay is display: table and the input is display: table-cell. This (along with absolute and relative positioning) keeps the input rigidly centered in the overlay.

  • rem units are used so if you want to scale the font-size up or down, just change the font-size of the <html> tag and everything adjusts accordingly:

      /* Change the 16px to whatever you want and everything scale to that value */
      html, 
      body {
        font: 400 16px/1.5 Consolas
      }
    

Demo

Note: Try keeping a key pressed continuously, and you'll see that there's no shifting.

var node = document.querySelector('#fSz');
node.oninput = setFontSize;

function setFontSize(e) {
  var tgt = e.target;
  var root = document.documentElement;
  root.style.setProperty(`--${tgt.id}`, `${tgt.valueAsNumber}px`);
}
:root {
  --fSz: 16px;
}

html,
body {
  font-size: var(--fSz);
  font-weight: 400;
  line-height: 1.5;
  font-family: Consolas, 'sans serif', monospace;
}

fieldset {
  position: relative;
  display: table;
  min-height: 5.5rem;
  padding: 0 0 0 0.3125rem;
  margin-top: 2em;
  overflow: visible;
}

fieldset * {
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  font-family: inherit;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}

legend {
  font-size: 1.2rem;
}

.overlay {
  display: table;
  position: relative;
  top: 0.3125rem;
  left: 0.9375rem;
  font-size: 1.2rem;
  font-weight: 900;
}

.overlay::after {
  content: '\ff3f\ff3f\ff3f\ff3f\ff3f\ff3f';
  font-size: 1.2rem;
  letter-spacing: 0.78rem;
}

@-moz-document url-prefix() {
  .overlay::after {
    content: '\2501\2501\2501\2501\2501\2501';
    text-shadow: 0.65rem 0px 0px #222;
    font-size: 1.37rem;
    letter-spacing: 1.2rem;
    line-height: 2;
  }
}

.hint {
  display: block;
  position: absolute;
  bottom: -2rem;
  left: 0.625rem;
  font-style: italic;
  font-size: 0.75rem;
}

#password-input {
  display: table-cell;
  border: 0px none transparent;
  outline: 0px none transparent;
  background: transparent;
  position: absolute;
  left: 0px;
  z-index: 1;
  overflow: hidden;
  line-height: 2;
  transform: translate(0.25rem, -1rem);
  letter-spacing: 1.25rem;
  font-size: 1.35rem;
  font-weight: 900;
}

sup {
  padding-top: 0.25rem;
  font-size: 0.65rem
}

.fc {
  display: block;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 3;
  font: 400 16px/1.5 Consolas;
  width: 50%;
}

#fSz {
  display: inline-block;
  padding-left: 8px;
  width: 52px;
  font: inherit;
  text-align: center;
}
<label for='fSz' class='fc'>Font-Size: 
  <input id='fSz' type='number' min='8' max='84' value='16' step='0.5'>&nbsp;px
  </label>

<fieldset>
  <legend>Enter New Pin</legend>
  <label for='chk' class='overlay'>
     <input type="password" name="password" id="password-input" inputmode="numeric" minlength="6" maxlength="6" size="19" value="123456" placeholder='123456'>
     </label>
  <label for="password-input" class="hint"><sup>&#128956;</sup>New pin must be 6 digit number only</label>

</fieldset>

9 Comments

Thanks Mr. O, I never thought to use the formatting comments on the answer before.
Your letter spacing is too small on Chromium on the Ubuntu OS: i.imgur.com/MT5dYpU.png
Change letter-spacing on .overlay and <input> and make sure they have the same value.
Actually after looking at the screenshot, I believe it's because Ubuntu OS doesn't recognizes Consolas font-family. Try a monospaced font comparable to Consolas.
Looks ugly on Firefox 62, Windows 10: i.sstatic.net/UeEHr.png
|
0

page result

This conventional solution may help for cross browser :

The HTML form :

<p class="text-center">Enter new pins</p>
     <form role="form" method="post">
        <div class="form-group text-center">

                <input class="inputbox"  maxlength="1" type="password" >
                <input class="inputbox"  maxlength="1" type="password" >
                <input class="inputbox"  maxlength="1" type="password" >
                <input class="inputbox"  maxlength="1" type="password" >
                <input class="inputbox"  maxlength="1" type="password" >
                <input class="inputbox"  maxlength="1" type="password" >

                <small class="text-danger">New pin must be 6 digit number only</small>      
            </div>

        <div class="form-group">
            <button type="submit" class="btn btn-primary btn-lg btn-block">Verify Pin
            </button>
        </div>
        <input id="code_hidden" maxlength="6" name="real_code" type="text" >
    </form>

We can see the result on input name = real_code. It must be type = 'hidden' on production. Change this maxlength when more field is required.

Style CSS :

<style>
.inputbox {
    background-color: #fff;
    border: none;
    border-bottom: thin solid gray;
    width: 20px;
    font-size: 24px;
    margin-bottom: 20px;
    margin-right: 5px;
}
</style>

Script part :

<script>
    $(function() {

    $(".inputbox").keyup(function () { 

        $(this).next('.inputbox').focus();

        var value = [];

        $('.inputbox').each(function() {
          value += $(this).val();  
        }); 

         $('#code_hidden').val(value); 
        });
    });

    </script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.