Adjust width of input field to its input

2019-01-01 10:34发布

<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.

24条回答
倾城一夜雪
2楼-- · 2019-01-01 10:48

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.

查看更多
姐姐魅力值爆表
3楼-- · 2019-01-01 10:48

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

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';
}
input{ 
  font-size:1.3em; 
  padding:5px; 
  margin-bottom: 1em;
}

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

查看更多
牵手、夕阳
4楼-- · 2019-01-01 10:49

Why not using just css?

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

function keyup(e) {
	document.getElementById('ghost').innerText = e.target.value;
}
#wrapper {
  position: relative;
  min-width: 30px;
  display: inline-block;
}

input {
  position: absolute;
  left:0;
  right:0;
  border:1px solid blue;
  width: 100%;
}

#ghost {
  color: transparent;
}
<div id="wrapper">
  <input onkeyup="keyup(event)">
  <div id="ghost"></div>
</div>

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

查看更多
流年柔荑漫光年
5楼-- · 2019-01-01 10:51

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.

查看更多
素衣白纱
6楼-- · 2019-01-01 10:52

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

查看更多
浪荡孟婆
7楼-- · 2019-01-01 10:52

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.

查看更多
登录 后发表回答