width:auto for <input> fields

Newbie CSS question. I thought width:auto for a display:block element meant 'fill available space'. However for an <input> element this doesn't seem to be the case. For example:

<body>
  <form style='background:red'>
    <input type='text' style='background:green; display:block; width:auto'>
  </form>
</body>

Two questions then:

  1. Is there a definition of exactly what width:auto does mean? The CSS spec seems vague to me, but maybe I missed the relevant section.

  2. Is there a way to achieve my expected behavior for a input field - ie. fill available space like other block level elements do?

Thanks!


An <input>'s width is generated from its size attribute. The default size is what's driving the auto width.

You could try width:100% as illustrated in my example below.

Doesn't fill width:

<form action='' method='post' style='width:200px;background:khaki'>
  <input style='width:auto' />
</form>

Fills width:

<form action='' method='post' style='width:200px;background:khaki'>
  <input style='width:100%' />
</form>

Smaller size, smaller width:

<form action='' method='post' style='width:200px;background:khaki'>
  <input size='5' />
</form>

UPDATE

Here's the best I could do after a few minutes. It's 1px off in FF, Chrome, and Safari, and perfect in IE. (The problem is #^&* IE applies borders differently than everyone else so it's not consistent.)

<div style='padding:30px;width:200px;background:red'>
  <form action='' method='post' style='width:200px;background:blue;padding:3px'>
    <input size='' style='width:100%;margin:-3px;border:2px inset #eee' />
    <br /><br />
    <input size='' style='width:100%' />
  </form>
</div>

"Is there a definition of exactly what width:auto does mean? The CSS spec seems vague to me, but maybe I missed the relevant section."

No one actually answered the above part of the original poster's question.

Here's the answer: http://www.456bereastreet.com/archive/201112/the_difference_between_widthauto_and_width100/

As long as the value of width is auto, the element can have horizontal margin, padding and border without becoming wider than its container...

On the other hand, if you specify width:100%, the element’s total width will be 100% of its containing block plus any horizontal margin, padding and border... This may be what you want, but most likely it isn’t.

To visualise the difference I made an example: http://www.456bereastreet.com/lab/width-auto/


Because input's width is controlled by it's size attribute, this is how I initialize an input width according to its content:

<input type="text" class="form-list-item-name" [size]="myInput.value.length" #myInput>

UPDATE (10/01/2022): My original answer was from the time I was studying Angular. If you need pure, Vanilla JavaScript the solution is even simpler:

<input type="text" oninput="this.size = this.value.length">

Or add an "input" event listener to your input html element and run a code like this:

const myInput = document.querySelector('input');
myInput.addEventListener('input', this.typing);

(...)

typing(e) {
  e.target.setAttribute('size', e.target.value.length);
}

Obs: Depending on the browser, input may restore to its default size of something between 150px and 250px if/when size gets the 0 value. In this case, just add +1 to value.length:

<input type="text" oninput="this.size = this.value.length + 1">

OR:

typing(e) {
  e.target.setAttribute('size', e.target.value.length + 1);
}