CSS field-sizing: the tiny property that replaces textarea resize JavaScript

CSS finally has a native way to auto-size form fields based on their content. The property is called field-sizing, and it is one of those small CSS features that does not look very exciting at first, but solves a problem web developers have been working around for years.

If you ever had to make a textarea grow as someone types, you probably know the usual solution. You add JavaScript, listen for input events, read the scroll height, update the height manually, and then handle all the edge cases when the field already has content, when the content is removed, when the layout changes, or when the browser behaves slightly differently than expected.

It works, but it always felt like something CSS should be able to do. Now it can.

The problem

By default, form fields have a fixed preferred size. A textarea has a size. An input has a size. A select has a size. If the content does not fit, the browser does not automatically resize the field to make everything visible. It usually clips the content or shows a scrollbar.

For textareas, this is especially common. You start typing a longer message, the field stays the same height, and suddenly you are writing inside a tiny box with a scrollbar. That is functional, but it does not feel great. For years, the common fix was JavaScript. With field-sizing: content, the browser can handle this itself.

The basic idea

The default value is:

field-sizing: fixed;

That keeps the normal browser behavior. The useful value is:

field-sizing: content;

That tells the browser to size the field based on its content. A simple example:

textarea { field-sizing: content; }

Now the textarea can grow to fit what is inside it. That is the whole feature. But, as usual with CSS, the one-line version is not always the version you want to ship.

Textareas

The most useful case is probably textareas. Without field-sizing, a textarea keeps its default size and adds a scrollbar when the content gets too long. With field-sizing: content, the textarea can grow with the content.

textarea { field-sizing: content; }

This already works, but the result can look strange if you do not give the browser some limits. The field might become too small when it is empty, it might grow in a direction you do not want, or it might become too tall and push the rest of the page down.

So in real projects, I would not use it alone. I would usually combine it with minimum and maximum sizes.

textarea { 
  field-sizing: content; 
  width: 100%; 
  min-width: 0; 
  max-width: 100%;  
  min-height: 4rem; 
  max-height: 12rem;
}

This keeps the textarea full width, gives it a reasonable minimum height, and stops it from growing forever. Once the content goes beyond the maximum height, the scrollbar comes back. That is usually what you want: the field grows while it is useful, but it does not take over the whole page.

Why the constraints matter

field-sizing: content does what you ask it to do. Sometimes that is the problem. If you tell a field to size itself based only on content, then an empty field can become very small, a long value can make it too wide, and a textarea can grow more than your layout can handle.

That is why I think this property should almost always be used with defensive CSS. Do not just tell the browser to resize the field. Also tell it what “too small” and “too large” mean in your design.

.auto-size-field { 
  field-sizing: content; 
  min-width: 12rem; 
  max-width: 100%; 
}

For textareas, that could look like this:

.auto-size-textarea { 
  field-sizing: content; 
  width: 100%; 
  min-width: 0; 
  max-width: 100%; 
  min-height: 4rem; 
  max-height: 12rem; 
}

This gives you the benefit of content-based sizing without letting the field break the layout.

Inputs

field-sizing is not only for textareas. It also works on inputs that accept text-like values, such as text, email, search, tel, url, password, and number inputs.

input { field-sizing: content; }

This can be useful for small inline fields, for example a search input, a tag field, a small settings input, or a dashboard control where the value should take only as much space as it needs. But again, you probably want limits.

input { 
  field-sizing: content; 
  min-width: 12rem; 
  max-width: 100%; 
}

Without a minimum width, an empty input can collapse too much. With a maximum width, a long value will not destroy the layout.

Placeholders count too

One useful detail is that placeholders are respected. If the input is empty and has placeholder text, the field can size itself to the placeholder.

<input placeholder="Search articles..." />
input { 
  field-sizing: content; 
  min-width: 12rem; 
  max-width: 100%;
}

That can be nice because the placeholder remains visible, but it is also something to watch out for. A very long placeholder can make the input wider than expected. If you are using translated text, the placeholder might be much longer in another language. So this is another reason to set a maximum size.

Select elements

Select elements also get more interesting with field-sizing. By default, a select dropdown is usually wide enough for the longest option. That means one long option can make the whole select wider, even when the currently selected option is short.

With field-sizing: content, the select can size itself to the selected option instead.

select { 
  field-sizing: content; 
  min-width: 10rem; 
  max-width: 100%;
}

This can be useful for compact filters, sorting controls, language switchers, and small admin interfaces.

<select>
  <option>Newest</option>
  <option>Price: low to high</option>
  <option>Price: high to low</option>
</select>
select { 
  field-sizing: content; 
  min-width: 10rem; 
  max-width: 100%;
} 

Now the select can be as wide as the selected value, instead of always reserving space for the longest one. That can make small interfaces feel cleaner. The tradeoff is that the select can change width when the selected option changes. Sometimes that is fine. Sometimes it is distracting. Use it where the layout can handle that movement.

Listbox selects

There is also a more niche select case. If a select uses the multiple attribute or has a size greater than one, it behaves like a listbox.

<select multiple>
  <option>Design</option>
  <option>Development</option> 
  <option>Strategy</option> 
</select>

With field-sizing: content, the listbox can size itself to show all the options.

select { 
  field-sizing: content; 
  min-width: 10rem; 
  max-width: 100%;
}

This is probably not the use case most people will reach for first, but it is good to know that the behavior is different from a normal dropdown.

File inputs

field-sizing: content can also affect file inputs. The field can resize based on the displayed filename after a file is selected.

input[type="file"] { 
  field-sizing: content; 
  min-width: 12rem; 
  max-width: 100%; 
}

I would be careful with this one. Filenames can be long. Very long. So if you use this on file inputs, make sure the layout still behaves well when someone uploads a file with a ridiculous name. Because someone will.

A practical default

For most projects, I would not apply this globally to every form field. I would create a small utility class and use it where the behavior actually improves the interface.

For textareas:

.auto-size-textarea { 
  field-sizing: content; 
  width: 100%; 
  min-width: 0; 
  max-width: 100%; 
  min-height: 4rem; 
  max-height: 12rem; 
}

For inline inputs:

.auto-size-input { 
  field-sizing: content; 
  min-width: 12rem; 
  max-width: 100%;
}

For selects:

.auto-size-select { 
  field-sizing: content; 
  min-width: 10rem; 
  max-width: 100%; 
}

Then use it only where it makes sense.

<textarea class="auto-size-textarea"></textarea>

<input class="auto-size-input" type="search" placeholder="Search..." />

<select class="auto-size-select">
  <option>Newest</option> 
  <option>Price: low to high</option> 
  <option>Price: high to low</option> 
</select>

That keeps the feature intentional.

Progressive enhancement

Browser support is much better now, but I would still treat this as progressive enhancement. If a browser does not support field-sizing, the form field will keep its normal fixed-size behavior. That is fine. The form should still work.

You can check the full field-sizing documentation on MDN, and current browser support on Can I Use.

You can wrap it in @supports if you want to be explicit:

@supports (field-sizing: content) {
  .auto-size-textarea {
    field-sizing: content;
    width: 100%;
    min-width: 0;
    max-width: 100%;
    min-height: 4rem;
    max-height: 12rem;
  }

  .auto-size-input {
    field-sizing: content;
    min-width: 12rem;
    max-width: 100%;
  }

  .auto-size-select {
    field-sizing: content;
    min-width: 10rem;
    max-width: 100%;
  }
}

This way, browsers that support it get the improved behavior. Browsers that do not support it keep the old behavior. Nothing breaks.

When not to use it

This is not something I would blindly add to every form. Fixed-size fields still make sense in many places, especially in checkout forms, login forms, strict grid layouts, fields that need to align perfectly, forms where layout movement would feel distracting, or interfaces with unpredictable translated text.

field-sizing is useful when content-based sizing improves the experience. It is not useful when the changing size becomes the thing users notice.

To recap

field-sizing lets form controls size themselves based on their content. The main value is:

field-sizing: content;

It is most useful for auto-growing textareas, but it also works on text-like inputs, select elements, listbox selects, and file inputs.

The important part is to use it with constraints. Set minimum sizes. Set maximum sizes. Do not let one long value break your layout.

For me, the best part is simple: this removes another small JavaScript dependency from our codebases. Not because JavaScript is bad, but because this is exactly the kind of thing the browser should be able to handle.

And now it can.