Dynamically expand height of input type "text" based on number of characters typed into field

Solution 1:

UPDATED[2]:

As scrollHeight is always equal to height, we have to set height to '1' before scrollHeight, then when we delete characters the <textarea> autofit:

$('textarea').on('keydown', function(e){
    if(e.which == 13) {e.preventDefault();}
}).on('input', function(){
    $(this).height(1);
    var totalHeight = $(this).prop('scrollHeight') - parseInt($(this).css('padding-top')) - parseInt($(this).css('padding-bottom'));
    $(this).height(totalHeight);
});

Fiddle:

http://jsfiddle.net/mJMpw/551/

UPDATED:

As friends said, <input type="text"/> has no line breaks. My suggest using <textarea> is:

$('textarea').on({input: function(){
    var totalHeight = $(this).prop('scrollHeight') - parseInt($(this).css('padding-top')) - parseInt($(this).css('padding-bottom'));
    $(this).css({'height':totalHeight});
}
});

Fiddle:

http://jsfiddle.net/mJMpw/548/

ORIGINAL ANSWER:

this is very ugly but you could do it like this:

$('input[type="text"]').on('keyup',function(){
    var text = $(this).val();
    var getWidth = $('<span class="getWidth" style="white-space:nowrap; width:auto;">' + text + '</span>').insertAfter(this);
    $(this).css({'width':getWidth.outerWidth()}).next('.getWidth').remove();
});

You have to specify the same fonts/padding property to .getWidth and you input:

input, .getWidth {
    font-family:arial;
    font-size:12px;
    font-weight:normal;
    letter-spacing:normal;
    padding:3px;
}

Fiddle:

http://jsfiddle.net/9SMRf/

Solution 2:

As others explained, input field can't have multiline text, you should use textarea to mimic an input field, and jQuery to make it auto resize vertically (with fixed width).

JS:

//This span is used to measure the size of the textarea
//it should have the same font and text with the textarea and should be hidden
var span = $('<span>').css('display','inline-block')
                      .css('word-break','break-all')
                      .appendTo('body').css('visibility','hidden');
function initSpan(textarea){
  span.text(textarea.text())
      .width(textarea.width())
      .css('font',textarea.css('font'));
}
$('textarea').on({
    input: function(){
       var text = $(this).val();      
       span.text(text);      
       $(this).height(text ? span.height() : '1.1em');
    },
    focus: function(){           
       initSpan($(this));
    },
    keypress: function(e){
       //cancel the Enter keystroke, otherwise a new line will be created
       //This ensures the correct behavior when user types Enter 
       //into an input field
       if(e.which == 13) e.preventDefault();
    }
});

CSS:

textarea {
  width:200px;
  resize:none;
  overflow:hidden;
  font-size:18px;
  height:1.1em;
  padding:2px;
}

Demo.

Updated Demo:

This new updated demo has some bugs fixed and it also supports Enter key, max-height limit, the width does not need to be set fixedly at first (instead we can set its min-width). It's much more full-featured.

Updated Demo

Solution 3:

Not mine but works great:

CSS

textarea {
     color: #444;
     padding: 5px;
}
.txtstuff {
    resize: none;
    overflow: hidden;
}
.hiddendiv {
    display: none;
    white-space: pre-wrap;
    word-wrap: break-word;
    overflow-wrap: break-word
}
.common {
    width: 500px;
    min-height: 50px;
    font-family: Arial, sans-serif;
    font-size: 13px;
    overflow: hidden;
}
.lbr {
    line-height: 3px;
}

HTML

<textarea id="comments" placeholder="Type many lines of texts in here and you will see magic stuff" class="common"></textarea>

SCRIPT

let txt = $('#comments'),
    txt.addClass('txtstuff');
let hiddenDiv = $(document.createElement('div')),
    hiddenDiv.addClass('hiddendiv common');
let content = null;

$('body').append(hiddenDiv);

txt.on('keyup', function () {
    content = $(this).val();
    content = content.replace(/\n/g, '<br>');
    hiddenDiv.html(content + '<br class="lbr">');
    $(this).css('height', hiddenDiv.height());
});

FIDDLE