[javascript] Adjust width of input field to its input

<html>
  <head>
  </head>
  <body>
    <input type="text" value="1" style="min-width:1px;" />
  </body>
</html>

This is my code and it is not working. Is there any other way in HTML, JavaScript, PHP or CSS to set minimum width?

I want a text input field with a dynamically changing width, so that the input field fluids around its contents. Every input has a built-in padding of 2em, that is the problem and second problem is that min-width ain't working on input at all.

If I set width more than it is needed than the whole program is messy, I need the width of 1px, more only if it's needed.

This question is related to javascript html css

The answer is


A bullet-proof, generic way has to:

  1. Take into account all possible styles of the measured input element
  2. Be able to apply the measurement on any input without modifying the HTML or

Codepen demo

_x000D_
_x000D_
var getInputValueWidth = (function(){
  // https://stackoverflow.com/a/49982135/104380
  function copyNodeStyle(sourceNode, targetNode) {
    var computedStyle = window.getComputedStyle(sourceNode);
    Array.from(computedStyle).forEach(key => targetNode.style.setProperty(key, computedStyle.getPropertyValue(key), computedStyle.getPropertyPriority(key)))
  }
  
  function createInputMeassureElm( inputelm ){
    // create a dummy input element for measurements
    var meassureElm = document.createElement('span');
    // copy the read input's styles to the dummy input
    copyNodeStyle(inputelm, meassureElm);
    
    // set hard-coded styles needed for propper meassuring 
    meassureElm.style.width = 'auto';
    meassureElm.style.position = 'absolute';
    meassureElm.style.left = '-9999px';
    meassureElm.style.top = '-9999px';
    meassureElm.style.whiteSpace = 'pre';
    
    meassureElm.textContent = inputelm.value || '';
    
    // add the meassure element to the body
    document.body.appendChild(meassureElm);
    
    return meassureElm;
  }
  
  return function(){
    return createInputMeassureElm(this).offsetWidth;
  }
})();


// delegated event binding
document.body.addEventListener('input', onInputDelegate)

function onInputDelegate(e){
  if( e.target.classList.contains('autoSize') )
    e.target.style.width = getInputValueWidth.call(e.target) + 'px';
}
_x000D_
input{ 
  font-size:1.3em; 
  padding:5px; 
  margin-bottom: 1em;
}

input.type2{
  font-size: 2.5em;
  letter-spacing: 4px;
  font-style: italic;
}
_x000D_
<input class='autoSize' value="type something">
<br>
<input class='autoSize type2' value="here too">
_x000D_
_x000D_
_x000D_


I think you're misinterpreting the min-width CSS property. min-width is generally used to define a minimum DOM width in a fluid layout, like:

input {
  width: 30%;
  min-width: 200px;
}

That would set the input element to a minimum width of 200 pixels. In this context, "px" stands for "pixels".

Now, if you're trying to check to make sure that input field contains at least one character when a user submits it, you'll need to do some form validation with JavaScript and PHP. If that is indeed what you're attempting to do, I'll edit this answer and do my best to help you out.


It's worth noting that a nice-looking resize can be done when the font is monospaced, so we can perfectly resize the input element using the ch unit.

Also in this approach we can update the width of the field by just updating a CSS variable (custom property) on input event and we should also take care of already pre-filled input on DOMContentLoaded event

Codepen demo


Markup

<input type="text" value="space mono font" class="selfadapt" />

CSS

:root { --size: 0; }

.selfadapt {
   padding: 5px;
   min-width: 10ch;
   font-family: "space mono";
   font-size: 1.5rem;
   width: calc(var(--size) * 1ch);
}

As a root variable we set --size: 0: this variable will contain the length of the input and it will be multiplied by 1ch inside the calc() expression. By default we could also set a min-width, e.g. 10ch

The Javascript part reads the length of the value inserted and updates the variable --size:

JS

let input = document.querySelector('.selfadapt');
let root  = document.documentElement.style;

/* on input event auto resize the field */
input.addEventListener('input', function() {
   root.setProperty('--size', this.value.length );
});

/* resize the field if it is pre-populated */
document.addEventListener("DOMContentLoaded", function() {
   root.setProperty('--size', input.value.length);
});

of course this still works even if you don't use monospaced font, but in that case you will need to change the calc() formula by multiplying the --size variable by another value (which it's strictly dependent on the font-family and font-size) different than 1ch.


Although this post is old already, I'd like to add a much more simple solution and don't know why only such huge and/or complex solutions have been provided.

Here's a simple function to get what is needed:

function resizeInput() {
    const input = document.getElementById('myInput');
    input.style.width = `${input.scrollWidth}px`;
};

Why not using just css?

<div id="wrapper">
  <input onkeyup="keyup(event)">
  <div id="ghost"></div>
</div>

_x000D_
_x000D_
function keyup(e) {_x000D_
 document.getElementById('ghost').innerText = e.target.value;_x000D_
}
_x000D_
#wrapper {_x000D_
  position: relative;_x000D_
  min-width: 30px;_x000D_
  display: inline-block;_x000D_
}_x000D_
_x000D_
input {_x000D_
  position: absolute;_x000D_
  left:0;_x000D_
  right:0;_x000D_
  border:1px solid blue;_x000D_
  width: 100%;_x000D_
}_x000D_
_x000D_
#ghost {_x000D_
  color: transparent;_x000D_
}
_x000D_
<div id="wrapper">_x000D_
  <input onkeyup="keyup(event)">_x000D_
  <div id="ghost"></div>_x000D_
</div>
_x000D_
_x000D_
_x000D_

wrapper {
  position: relative;
  min-width: 30px;
  border: 1px solid red;
  display: inline-block;
}

input {
  position: absolute;
  left:0;
  right:0;
  width: 100%;
}

#ghost {
  color: transparent;
}

this code was introduced by @Iain Todd to and I thought I should share it


You would like to change the size attribute as the text changes.

# react

const resizeInput = (e) => {
  e.target.setAttribute('size', e.target.value.length || 1);
}

<input 
  onChange={resizeInput}
  size={(propertyInput.current && propertyInput.current.value.length) || 1}
  ref={propertyInput} 
/>

  

Here is a plain JS and a jQuery plugin I wrote that will handle resizing an input element using a canvas and the font size / family to determine the actual string length when rendered. (only works in > IE9, chrome, safari, firefox, opera and most other major browsers that have implemented the canvas element).

PlainJS:

function autoSize(input, o) {
    o || (o = {});
    o.on || (o.on = 'keyup');

    var canvas = document.createElement('canvas');
    canvas.setAttribute('style', 'position: absolute; left: -9999px');
    document.body.appendChild(canvas);

    var ctx = canvas.getContext('2d');

    input.addEventListener(o.on, function () {
        ctx.font = getComputedStyle(this,null).getPropertyValue('font');
        this.style.width = ctx.measureText(this.value + '  ').width + 'px';
    });
}

//Usage
autoSize(document.getElementById('my-input'));

jQuery Plugin:

$.fn.autoSize = function(o) {
  o = $.extend({}, {
    on: 'keyup'
  }, o);

  var $canvas = $('<canvas/>').css({position: 'absolute', left: -9999});
  $('body').append($canvas);

  var ctx = $canvas[0].getContext('2d');

  return this.on(o.on, function(){
    var $this = $(this);
    ctx.font = $this.css('font');
    $this.width(ctx.measureText($this.val()).width + 'px');
  })
}

//Usage:
$('#my-input').autoSize();

Note: this will not handle text-transforms, line spacing and letter spacing, and probably some other text size changing properties. To handle text-transform property set and adjust the text value to match that property. The others are probably fairly straight forward. I will implement if this starts gaining some traction...


Here is an alternative way to solve this using a DIV and the 'contenteditable' property:

HTML:

<div contenteditable = "true" class = "fluidInput" data-placeholder = ""></div>

CSS: (to give the DIV some dimensions and make it easier to see)

.fluidInput {

    display         : inline-block;
    vertical-align  : top;

    min-width       : 1em;
    height          : 1.5em;

    font-family     : Arial, Helvetica, sans-serif;
    font-size       : 0.8em;
    line-height     : 1.5em;

    padding         : 0px 2px 0px 2px;
    border          : 1px solid #aaa;
    cursor          : text;
}


.fluidInput * {

    display         : inline;

}


.fluidInput br  {

    display         : none;

}


.fluidInput:empty:before {

    content         : attr(data-placeholder);
    color           : #ccc;

}

Note: If you are planning on using this inside of a FORM element that you plan to submit, you will need to use Javascript / jQuery to catch the submit event so that you can parse the 'value' ( .innerHTML or .html() respectively) of the DIV.


You could do something like this

// HTML
<input id="input" type="text" style="width:3px" />
// jQuery
$(function(){
  $('#input').keyup(function(){
    $('<span id="width">').append( $(this).val() ).appendTo('body');
    $(this).width( $('#width').width() + 2 );
    $('#width').remove();
  });
});

?

?


If you use Bootstrap, it could be done very easily:

<div contenteditable="true" class="form-control" style="display: inline"></div>

You will just need to fetch div's content and put it in a hidden input before submitting the form.


You can do it even simpler in angularjs using the built-in ng-style directive.

In your html:

  <input ng-style="inputStyle(testdata)" ng-model="testdata" />

In your controller:

 $scope.testdata = "whatever";

 $scope.inputStyle = function(str) {
    var charWidth = 7;
    return  {"width": (str.length +1) * charWidth + "px" };
    };

In your css:

input { font-family:monospace; font-size:12px; }

Adjust the charWidth to match the width of your font. It seems to be 7 at a font-size of 12px;


To calculate the width of the current input, you'll have to embed it in a temporary span element, attach that thing to the DOM, get the computed width (in pixels) using the scrollWidth property and remove the span again. Of course you'll have to ensure that the same font family, font size, etc., is used in the input as well as in the span element. Therefore I assigned the same class to them.

I attached the function to the keyup event, as on keypress the input character is not yet added to the input value, so that will result in the wrong width. Unfortunately, I don't know how to get rid of the scrolling of the input field (when adding characters to the end of the field); it scrolls, because the character is added and shown before adjustWidthOfInput() is called. And, as said, I can't do this the other way round because then you'll have the value of the input field before the pressed character is inserted. I'll try to solve this issue later.

BTW, I only tested this in Firefox (3.6.8), but you'll get the point, I hope.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Get/set width of &lt;input&gt;</title>
    <style>
      body {
        background: #666;
      }

      .input-element {
        border: 0;
        padding: 2px;
        background: #fff;
        font: 12pt sans-serif;
      }

      .tmp-element {
        visibility: hidden;
        white-space: pre;
      }
    </style>
  </head>
  <body>
    <input id="theInput" type="text" class="input-element" value="1">
    <script>
      var inputEl = document.getElementById("theInput");

      function getWidthOfInput() {
        var tmp = document.createElement("span");
        tmp.className = "input-element tmp-element";
        tmp.innerHTML = inputEl.value.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
        document.body.appendChild(tmp);
        var theWidth = tmp.getBoundingClientRect().width;
        document.body.removeChild(tmp);
        return theWidth;
      }

      function adjustWidthOfInput() {
        inputEl.style.width = getWidthOfInput() + "px";
      }

      adjustWidthOfInput();
      inputEl.onkeyup = adjustWidthOfInput;
    </script>
  </body>
</html>

Here is my 2 cents. Create an empty invisible div. Fill it with the input content and return the width to the input field. Match text styles between each box.

_x000D_
_x000D_
$(".answers_number").keyup(function(){_x000D_
    $( "#number_box" ).html( $( this ).val() );_x000D_
    $( this ).animate({_x000D_
        width: $( "#number_box" ).width()+20_x000D_
        }, 300, function() {_x000D_
    });_x000D_
});
_x000D_
#number_box {_x000D_
   position: absolute;_x000D_
   visibility: hidden;_x000D_
   height: auto;_x000D_
   width: auto;_x000D_
   white-space: nowrap;_x000D_
   padding:0 4px;_x000D_
   /*Your font styles to match input*/_x000D_
   font-family:Arial;_x000D_
   font-size: 30px; _x000D_
}_x000D_
    _x000D_
.answers_number {_x000D_
   font-size: 30px; _x000D_
   font-family:Arial;_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<input type="number" class="answers_number" />_x000D_
<div id="number_box">_x000D_
</div>
_x000D_
_x000D_
_x000D_


Based off Michael's answer, I have created my own version of this using jQuery. I think it is a cleaner/shorter version of most answers here and it seems to get the job done.

I am doing the same thing as most of the people here by using a span to write the input text into then getting the width. Then I am setting the width when the actions keyup and blur are called.

Here is a working codepen. This codepen shows how this can be used with multiple input fields.

HTML Structure:

<input type="text" class="plain-field" placeholder="Full Name">
<span style="display: none;"></span>

jQuery:

function resizeInputs($text) {
    var text = $text.val().replace(/\s+/g, ' '),
        placeholder = $text.attr('placeholder'),
        span = $text.next('span');
        span.text(placeholder);
    var width = span.width();

    if(text !== '') {
        span.text(text);
    var width = span.width();
    }

    $text.css('width', width + 5);
};

The function above gets the inputs value, trims the extra spaces and sets the text into the span to get the width. If there is no text, it instead gets the placeholder and enters that into the span instead. Once it enters the text into the span it then sets the width of the input. The + 5 on the width is because without that the input gets cut off a tiny bit in the Edge Browser.

$('.plain-field').each(function() {
    var $text = $(this);
    resizeInputs($text);
});

$('.plain-field').on('keyup blur', function() {
    var $text = $(this);
    resizeInputs($text);
});

$('.plain-field').on('blur', function() {
    var $text = $(this).val().replace(/\s+/g, ' ');
    $(this).val($text);
});

If this could be improved please let me know as this is the cleanest solution I could come up with.


Just adding on top of other answers.

I noticed that nowadays in some browsers the input field has a scrollWidth. Which means:

this.style.width = this.scrollWidth + 'px';

should work nicely. tested in chrome, firefox and safari.

For deletion support, you can add '=0' first and then readjust.

this.style.width = 0; this.style.width = this.scrollWidth + 'px';

Quite simple:

oninput='this.style.width = (this.scrollWidth - N) + "px";'

Where N is some number (2 in the example, 17 on something I'm developing) that is determined experimentally.

Subtracting N prevents this strange extrenuous space from accumulating long before the text reaches the end of the text box.

Compare. Pay careful attention to how the size changes after even just the first character.

_x000D_
_x000D_
<p>Subtracting N:</p>    _x000D_
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth-2) + "px";'>_x000D_
_x000D_
<p>Not Subtracting N:</p>    _x000D_
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth) + "px";'>
_x000D_
_x000D_
_x000D_


FOR A NICER LOOK&FEEL

You should use jQuery keypress() event in combination with String.fromCharCode(e.which) to get the pressed character. Hence you can calculate what your width will be. Why? Because it will look a lot more sexy :)

Here is a jsfiddle that results in a nice behaviour compared to solutions using the keyup event : http://jsfiddle.net/G4FKW/3/

Below is a vanilla JS which listens to the input event of an <input> element and sets a span sibling to have the same text value in order to measure it.

_x000D_
_x000D_
document.querySelector('input').addEventListener('input', onInput)_x000D_
_x000D_
function onInput(){_x000D_
    var spanElm = this.nextElementSibling;_x000D_
    spanElm.textContent = this.value; // the hidden span takes the value of the input; _x000D_
    this.style.width = spanElm.offsetWidth + 'px'; // apply width of the span to the input_x000D_
};
_x000D_
/* it's important the input and its span have same styling */_x000D_
input, .measure {_x000D_
    padding: 5px;_x000D_
    font-size: 2.3rem;_x000D_
    font-family: Sans-serif;_x000D_
    white-space: pre; /* white-spaces will work effectively */_x000D_
}_x000D_
_x000D_
.measure{  _x000D_
  position: absolute;_x000D_
  left: -9999px;_x000D_
  top: -9999px;_x000D_
}
_x000D_
<input type="text" />_x000D_
<span class='measure'></span>
_x000D_
_x000D_
_x000D_


You can set an input's width using the size attribute as well. The size of an input determines it's width in characters.

An input could dynamically adjust it's size by listening for key events.

For example

$("input[type='text']").bind('keyup', function () {
    $(this).attr("size", $(this).val().length );
});

JsFiddle here


In modern browser versions, CSS unit ch is also available. To my understanding, it is font-independent unit, where 1ch equals to width of character 0 (zero) in any given font.

Thus, something as simple as following could be used as resize function:

_x000D_
_x000D_
var input = document.querySelector('input'); // get the input element_x000D_
input.addEventListener('input', resizeInput); // bind the "resizeInput" callback on "input" event_x000D_
resizeInput.call(input); // immediately call the function_x000D_
_x000D_
function resizeInput() {_x000D_
  this.style.width = this.value.length + "ch";_x000D_
}
_x000D_
input{ font-size:1.3em; padding:.5em; }
_x000D_
<input>
_x000D_
_x000D_
_x000D_

That example would resize "elem" to length of the value + 2 characters extra.


Better is onvalue:

<input id="txt" type="text" onvalue="this.style.width = ((this.value.length + 1) * 8) + 'px';">

It also involves pasting, dragging and dropping, etc.


Here is a solution without monospaced font needed, with only a very small piece code of javascript, does not need to calculate computed styles, and even supports IME, supports RTL text.

_x000D_
_x000D_
// copy the text from input to the span
    $(function () {
      $('.input').on('input', function () { $('.text').text($('.input').val()); });
    });
_x000D_
    * {
      box-sizing: border-box;
    }
    
    .container {
      display: inline-block;
      position: relative;
    }
    
    .input,
    .text {
      margin: 0;
      padding: 2px 10px;
      font-size: 24px;
      line-height: 32px;
      border: 1px solid #ccc;
      box-radius: 3px;
      height: 36px;
      font: 20px/20px sans-serif;
      /* font: they should use same font; */
    }

    .text {
      padding-right: 20px;
      display: inline-block;
      visibility: hidden;
      white-space: pre;
    }
    
    .input {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      width: 100%;
    }
    
_x000D_
<script src="https://code.jquery.com/jquery-3.2.0.min.js"></script>

<div class="container">
  <span class="text">
    some text
  </span>
  <input class="input" value="some text" />
</div>
_x000D_
_x000D_
_x000D_

Use the span.text to fit width of text, and let the input have same size with it by position: absolute to the container. Copy value of input to the span every time it changes (you may change this piece of code to vanilla JS easily, or use features provided by your frontend framework). So the input will just fit the size of its content.


You can just set size attribute. If you're using one of reactive frameworks, the following will be enough:

<input size="{{ yourValue.length }}" [value]="yourValue" />

but if you're using pure js, you should set event handlers, like:

<input oninput="this.setAttribute('size', this.value.length)" />


The best solution is <input ... size={input.value.length} />


I just spend some time figuring out how to do it.
Actually the simplest way I found is to move input value to span just before the input, keeping input 1 symbol width. Though I can't be sure that it fit for your initial need.
Maybe it some extra code, but in react+flux based application it is quite natural solution.


This answer provides one of the most accurate methods of retrieving text width available in the browser and is more accurate than the accepted answer. It uses the canvas html5 element and unlike other answers does not add the element into the DOM and thus avoids any reflow issues caused by excessively adding elements to the DOM.

Read more about the Canvas element here in relation to text width.

NOTE: According to MDN the shorthand versions of the getPropertyValue() method such as font can be unreliable. I'd recommend getting the values singularly to improve compatibility. I only used it here for speed.

_x000D_
_x000D_
/**_x000D_
 * returns the width of child text of any DOM node as a float_x000D_
 */_x000D_
function getTextWidth(el) {_x000D_
  // uses a cached canvas if available_x000D_
  var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));_x000D_
  var context = canvas.getContext("2d");_x000D_
  // get the full font style property_x000D_
  var font = window.getComputedStyle(el, null).getPropertyValue('font');_x000D_
  var text = el.value;_x000D_
  // set the font attr for the canvas text_x000D_
  context.font = font;_x000D_
  var textMeasurement = context.measureText(text);_x000D_
  return textMeasurement.width;_x000D_
}_x000D_
_x000D_
var input = document.getElementById('myInput');_x000D_
// listen for any input on the input field_x000D_
input.addEventListener('input', function(e) {_x000D_
  var width = Math.floor(getTextWidth(e.target));_x000D_
  // add 10 px to pad the input._x000D_
  var widthInPx = (width + 10) + "px";_x000D_
  e.target.style.width = widthInPx;_x000D_
}, false);
_x000D_
#myInput {_x000D_
  font: normal normal 400 normal 18px / normal Roboto, sans-serif;_x000D_
  min-width: 40px;_x000D_
}
_x000D_
<input id="myInput" />
_x000D_
_x000D_
_x000D_


This is an Angular-specific answer, but this worked for me and has been very satisfying in terms of its simplicity and ease-of-use:

<input [style.width.ch]="value.length" [(ngModel)]="value" />

It automatically updates via the character units in Jani's answer.


Here's a modification of Lyth's answer that takes into account:

  • Deletion
  • Initialisation
  • Placeholders

It also allows for any number of input fields! To see it in action: http://jsfiddle.net/4Qsa8/

Script:

$(document).ready(function () {
    var $inputs = $('.resizing-input');

    // Resize based on text if text.length > 0
    // Otherwise resize based on the placeholder
    function resizeForText(text) {
        var $this = $(this);
        if (!text.trim()) {
            text = $this.attr('placeholder').trim();
        }
        var $span = $this.parent().find('span');
        $span.text(text);
        var $inputSize = $span.width();
        $this.css("width", $inputSize);
    }

    $inputs.find('input').keypress(function (e) {
        if (e.which && e.charCode) {
            var c = String.fromCharCode(e.keyCode | e.charCode);
            var $this = $(this);
            resizeForText.call($this, $this.val() + c);
        }
    });

    // Backspace event only fires for keyup
    $inputs.find('input').keyup(function (e) { 
        if (e.keyCode === 8 || e.keyCode === 46) {
            resizeForText.call($(this), $(this).val());
        }
    });

    $inputs.find('input').each(function () {
        var $this = $(this);
        resizeForText.call($this, $this.val())
    });
});

Style:

.resizing-input input, .resizing-input span {
    font-size: 12px;
    font-family: Sans-serif;
    white-space: pre;
    padding: 5px;
}

HTML:

<div class="resizing-input">
    <input type="text" placeholder="placeholder"/>
    <span  style="display:none"></span>
</div>

_x000D_
_x000D_
$(document).ready(function() {_x000D_
  var $inputs = $('.resizing-input');_x000D_
_x000D_
  // Resize based on text if text.length > 0_x000D_
  // Otherwise resize based on the placeholder_x000D_
  function resizeForText(text) {_x000D_
    var $this = $(this);_x000D_
    if (!text.trim()) {_x000D_
      text = $this.attr('placeholder').trim();_x000D_
    }_x000D_
    var $span = $this.parent().find('span');_x000D_
    $span.text(text);_x000D_
    var $inputSize = $span.width();_x000D_
    $this.css("width", $inputSize);_x000D_
  }_x000D_
_x000D_
  $inputs.find('input').keypress(function(e) {_x000D_
    if (e.which && e.charCode) {_x000D_
      var c = String.fromCharCode(e.keyCode | e.charCode);_x000D_
      var $this = $(this);_x000D_
      resizeForText.call($this, $this.val() + c);_x000D_
    }_x000D_
  });_x000D_
_x000D_
  // Backspace event only fires for keyup_x000D_
  $inputs.find('input').keyup(function(e) {_x000D_
    if (e.keyCode === 8 || e.keyCode === 46) {_x000D_
      resizeForText.call($(this), $(this).val());_x000D_
    }_x000D_
  });_x000D_
_x000D_
  $inputs.find('input').each(function() {_x000D_
    var $this = $(this);_x000D_
    resizeForText.call($this, $this.val())_x000D_
  });_x000D_
});
_x000D_
.resizing-input input,_x000D_
.resizing-input span {_x000D_
  font-size: 12px;_x000D_
  font-family: Sans-serif;_x000D_
  white-space: pre;_x000D_
  padding: 5px;_x000D_
}
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>_x000D_
<div class="resizing-input">_x000D_
  First:_x000D_
  <input type="text" placeholder="placeholder" />_x000D_
  <span style="display:none"></span>_x000D_
</div>_x000D_
<br>
_x000D_
_x000D_
_x000D_


I really liked Lyth's answer, but also really wanted it to:

  1. Handle backspace and delete
  2. Not require you to manually add an adjacent tag.
  3. Enforce a min width.
  4. Automatically be applied to elements with a specific class

I adapted his JSFiddle and came up with this. One improvement not present in this fiddle would be to use something like the jQuery CSS Parser to actually read the initial width from the input.textbox-autosize rule, and use that as the minWidth. Right I'm simply using an attribute on the , which makes for a compact demo but is not ideal. as it requires an extra attribute on each input. You might also just want to put the minWidth as 100 right in the JavaScript.

HTML:

<div id='applicationHost'>
<div>Name:   <input class='textbox-autosize' data-min-width='100' type="text" /></div>
<div>Email:  <input class='textbox-autosize' data-min-width='100' type="email" /></div>
<div>Points: <input class='textbox-autosize' data-min-width='100' type="number" /></div>
</div>

CSS:

#applicationHost {
    font-family: courier;
    white-space: pre;
}

input.textbox-autosize, span.invisible-autosize-helper {
    padding:0;
    font-size:12px;
    font-family:Sans-serif; 
    white-space:pre;
}
input.textbox-autosize {
    width: 100px; /* Initial width of textboxes */
}

/*
In order for the measurements to work out, your input and the invisible
span need to have the same styling.
*/

JavaScript:

$('#applicationHost').on('keyup', '.textbox-autosize', function(e) {
    // Add an arbitary buffer of 15 pixels.
    var whitespaceBuffer = 15;
    var je = $(this);
    var minWidth = parseInt(je.attr('data-min-width'));
    var newVal = je.val();
    var sizingSpanClass = 'invisible-autosize-helper';
    var $span = je.siblings('span.' + sizingSpanClass).first();
    // If this element hasn't been created yet, we'll create it now.
    if ($span.length === 0) {
        $span = $('<span/>', {
            'class': sizingSpanClass,
            'style': 'display: none;'
        });
        je.parent().append($span);
    }
    $span = je.siblings('span').first();
    $span.text(newVal) ; // the hidden span takes 
    // the value of the input
    $inputSize = $span.width();
    $inputSize += whitespaceBuffer;
    if($inputSize > minWidth)
        je.css("width", $inputSize) ; // apply width of the span to the input
    else
        je.css("width", minWidth) ; // Ensure we're at the min width
});

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width