skip to Main Content

Use the text type input so that its completion is similar to the figure below. The input will accept one character per "square". It is not allowed to use multiple inputs for this field.

Is there a way to recreate the following input without any additional inputs?

The input image

The input should be at most 20 characters, each box representing one character.
The input will accept one character per box.

This is what I’ve done so far but with this approach, if I increase the font size everything falls apart

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    padding: 2rem;
}

.input-container {
    display: flex;
    gap: 1rem;
}

.input-container input {
    height: 1rem;
    letter-spacing: 8px;
    font-size: 15px;
    border: none;
    outline: none;
    background-color: transparent;
    font-family: monospace;
}

.box-container {
    display: flex;
    position: absolute;
    top: 50%;
    transform: translate(0, -50%);
    z-index: -1;
}

.box {
    width: 16px;
    height: 16px;    
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 1);
}
<body>
    <div class="input-container">
        <label for="name">Nume</label>
        <div style="position: relative">
            <input id="name" type="text" size="40" maxlength="20" />
            <div class="box-container">
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
                <div class="box"></div>
            </div>
        </div>
    </div>
</body>

2

Answers


  1. Like j08691 suggested, use relative units for your font and sizing. I’ve applied it with a custom property for easy updates.

    I’ve also shifted the characters to center them with some padding on the input.

    Demo using 1 rem:

    :root {
      --baseFontSize: 1rem;
    }
    
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      padding: 2rem;
    }
    
    .input-container {
      display: flex;
      gap: 1rem;
    }
    
    .input-container input {
      height: var(--baseFontSize);
      padding-left: calc(var(--baseFontSize) / 4);
      letter-spacing: calc(var(--baseFontSize) * .45);
      font-size: var(--baseFontSize);
      border: none;
      outline: none;
      background-color: transparent;
      font-family: monospace;
    }
    
    .box-container {
      display: flex;
      position: absolute;
      top: 50%;
      transform: translate(0, -50%);
      z-index: -1;
    }
    
    .box {
      width: var(--baseFontSize);
      height: var(--baseFontSize);
      box-shadow: 0 0 0 1px rgba(0, 0, 0, 1);
    }
    <body>
      <div class="input-container">
        <label for="name">Nume</label>
        <div style="position: relative">
          <input id="name" type="text" size="40" maxlength="20" />
    
          <div class="box-container">
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
          </div>
        </div>
      </div>
    </body>

    Demo using 2 rem:

    :root {
      --baseFontSize: 2rem;
    }
    
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      padding: 2rem;
    }
    
    .input-container {
      display: flex;
      gap: 1rem;
    }
    
    .input-container input {
      height: var(--baseFontSize);
      padding-left: calc(var(--baseFontSize) / 4);
      letter-spacing: calc(var(--baseFontSize) * .45);
      font-size: var(--baseFontSize);
      border: none;
      outline: none;
      background-color: transparent;
      font-family: monospace;
    }
    
    .box-container {
      display: flex;
      position: absolute;
      top: 50%;
      transform: translate(0, -50%);
      z-index: -1;
    }
    
    .box {
      width: var(--baseFontSize);
      height: var(--baseFontSize);
      box-shadow: 0 0 0 1px rgba(0, 0, 0, 1);
    }
    <body>
      <div class="input-container">
        <label for="name">Nume</label>
        <div style="position: relative">
          <input id="name" type="text" size="40" maxlength="20" />
    
          <div class="box-container">
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
          </div>
        </div>
      </div>
    </body>
    Login or Signup to reply.
  2. To get your code easy to scale you have to define the values in a way to depend on each other. They have to be linked mathematically.

    This can be achieved by using variables in the CSS:

    :root {
        font-size: 16px;      /* define "1rem" */
        
        /* CONFIG Input Area */
        --input-font: 'Noto Sans Mono',monospace;
        --input-letter-relation: 0.6018;    /* relation (no unit) - justify X/Y-relation of the font */
    
                                            /* Use relative units (not px oder pt) */
        --input-font-size:       1.5rem;    /* Set the font-size of the input font */
        --input-letter-spacing:  0.0rem;    /* Set the letter-spacing for the  */
        --box2font-height:       1.0;       /* relation (no unit) - justify the vertical size of the caret relative to the font-size" */
        
        /* Link the Input boxes to the font-size */
        --input-height-box: calc(var(--input-font-size) * var(--box2font-height));
        --input-width-box:  calc(var(--input-font-size) * var(--input-letter-relation) +  var(--input-letter-spacing));
        
    }
    
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }
    
    body {
        padding: 2rem;
    }
    
    .input-container {
        display: flex;
        gap: 1rem;
    }
    
    .input-container input {
        /*  height: var(--input-font-size);   */
        letter-spacing: var(--input-letter-spacing);
        font-size: var(--input-font-size);
        border: none;
        outline: none;
        background-color: transparent;
        font-family: var(--input-font);
    }
    
    .box-container {
        display: flex;
        position: absolute;
        top: 50%;
        transform: translate(0, -50%);
        z-index: -1;
    }
    
    .box {
        width: var(--input-width-box);
        height: var(--input-height-box);    
        box-shadow: 0 0 0 1px rgba(0, 0, 0, 1);
    }
    <head>
        <link href='https://fonts.googleapis.com/css?family=Noto+Sans+Mono' rel='stylesheet'>
    </head>
    
    <body>
        <div class="input-container">
            <label for="name">Nume</label>
            <div style="position: relative">
                <input id="name" type="text" size="40" maxlength="20" />
                <div class="box-container">
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                    <div class="box"></div>
                </div>
            </div>
        </div>
    </body>

    Just fit these values to your needs:

    --input-font-size:       1.5rem;    /* Set the font-size of the input font */
    --input-letter-spacing:  0.0rem;    /* Set the letter-spacing for the  */
    --box2font-height:       1.0;       /* relation (no unit) - justify the vertical size of the caret relative to the font-size" */
    

    Unfortunately, your concept lacks in one central point: "monospace" is a local resource.

    Which font will be used at the client depends on the operating system, the web browser and user settings. As fonts have different spacing, each font may need to be justified (variable --input-letter-relation) to make it run synchronous with the boxes in the background.

    The only solution to solve this (using your concept) is to provide the font used.

    I decided to "Noto Sans Mono". It is widely spread due to the "Noto" universal fonts, is free to download and can be addressed at googleapis.com, so this demo should run properly.


    To justify a font

    • set the letter-spacing to 1.0
    • the font as large as possible to fit the input line to your screen
    • fill all input fields, the first and the last one with a zero.

    Now tune the variable --input-letter-relation to fit the first an last zero into their field identically.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search