Volver a las notas

CSS field-sizing: campos que crecen al escribir

25 de octubre de 2026·
cssformsbaselineux
Demo en vivoAbrir a pantalla completa

Antes, para que un textarea creciera al escribir hacía falta un script que midiera scrollHeight con cada tecla. Ahora basta una línea de CSS: field-sizing: content. Firefox 152 la incorporó el 16 de junio de 2026, así que la propiedad ya es Baseline y funciona en Chrome, Edge, Firefox y Safari.

Escribe en la demo de arriba o pulsa «Escribir por mí». Los huecos de la frase se ensanchan con cada letra, el desplegable se encoge hasta la opción que eliges y el chat gana una línea cada vez hasta llegar a su tope. Si cambias el interruptor a fixed, vuelves al comportamiento de siempre con el mismo HTML.

Qué es y por qué importa

Los controles de formulario siempre han tenido un tamaño que no depende de lo que llevan dentro. Un <input> mide lo mismo con «Al» que con una dirección postal entera, un <textarea> ocupa las rows y cols que le toquen y un <select> es tan ancho como su opción más larga. La especificación los llama «elementos con tamaño preferido por defecto».

field-sizing admite dos valores:

  • fixed: el valor por defecto. El control conserva ese tamaño preferido por defecto.
  • content: el navegador calcula el tamaño del control a partir de su contenido y no hace caso del tamaño por defecto.

No tiene más API que esa. Lo que la hace interesante es la cantidad de pequeñas molestias que quita: cajas de chat, comentarios, formularios de «rellena el hueco», campos de etiquetas, filtros compactos con un <select> que no debería reservar sitio para su opción más larga. Antes todo eso suponía JavaScript que medía texto, se ejecutaba en cada evento input y chocaba con las fuentes que aún no habían cargado.

Cómo funciona

Este es el CSS de la demo, recortado a lo esencial:

/* La técnica: los campos miden lo que su contenido */
input, textarea, select {
  field-sizing: content;
}

/* Huecos en línea: nunca más estrechos de 3 caracteres
   ni más anchos que su contenedor */
.sentence input,
.sentence select {
  min-width: 3ch;
  max-width: 100%;
}

/* Chat: ancho fijo, la altura crece hasta un tope y luego hay scroll */
.composer textarea {
  width: 100%;
  min-height: 2.75em;
  max-height: 7.5em;
  resize: none;
}

Ahí pasan tres cosas:

  1. Los campos de texto se ajustan a su texto. Los tipos text, email, search, tel, url, number y password crecen y encogen con el valor. Si hay placeholder, el campo es lo bastante ancho para mostrarlo.
  2. El textarea crece primero a lo ancho y luego hacia abajo. Si nada lo frena, un textarea con field-sizing: content se comporta como un campo de una línea. Cuando ya no puede ensancharse, porque tiene un width fijo o llega a su max-width, empieza a añadir líneas. Al llegar a max-height aparece la barra de scroll. Por eso el chat de la demo lleva width: 100%: el ancho se queda quieto y solo cambia la altura. La especificación usa justo este caso como ejemplo.
  3. El desplegable se ajusta a la opción elegida. Un <select> normal cambia de ancho cuando eliges otra opción. Una lista (multiple, o size mayor que 1) enseña todas las opciones en lugar de hacer scroll.

En la demo, el único JavaScript que toca tamaños es el ResizeObserver que pinta las medidas en píxeles, más el plan B del que hablo abajo. Todo el crecimiento es CSS.

Las trampas

Comprobé cada una en Chromium con una página de prueba antes de escribirla. Coinciden con lo que describe MDN:

  • Pon siempre un min-width. Un input vacío con field-sizing: content y sin mínimo mide lo que el cursor de texto. En mi prueba, 9 píxeles. Por eso la demo usa min-width: 3ch.
  • size, rows y cols dejan de hacer nada. Definen el tamaño preferido por defecto, y content lo ignora. Un <input size="40"> con field-sizing: content midió exactamente lo mismo que uno sin el atributo.
  • Un width y un height fijos anulan el efecto. Si fijas los dos, el control vuelve a tener un tamaño fijo. Usa min-* y max-* para ponerle límites, o fija solo el ancho, como en el chat.
  • maxlength también pone tope al tamaño, porque el campo deja de crecer cuando no caben más caracteres.
  • Ojo con el contenedor. En un grid de CSS, el tamaño mínimo automático de un elemento puede hacer que un campo que crece empuje toda la tarjeta y la saque de la pantalla. Es justo lo que le pasó a la primera versión de esta demo a 375 px. Se arregla con grid-template-columns: minmax(0, 1fr) en el padre, o con min-width: 0 en el elemento.

Soporte en navegadores

Según los datos de compatibilidad de MDN, Chrome y Edge 123 (marzo de 2024) fueron los primeros, después llegó Safari 26.2 (diciembre de 2025) y por último Firefox 152 (junio de 2026). Por eso es Baseline «recién disponible» desde el 16 de junio de 2026. Durante unos meses todavía habrá gente con navegadores que no la tienen.

La buena noticia es que el plan B sale gratis: un navegador que no entiende field-sizing ignora la declaración y dibuja el formulario como siempre. Si el tamaño de antes te vale, no necesitas nada más. Si no, comprueba el soporte y carga el truco de siempre solo cuando falte la propiedad:

if (!CSS.supports('field-sizing', 'content')) {
  // Truco de siempre: medir y fijar el tamaño a mano
  textarea.addEventListener('input', () => {
    textarea.style.height = 'auto';
    textarea.style.height = textarea.scrollHeight + 'px';
  });
}

La demo hace exactamente eso y muestra un aviso cuando funciona con el plan B. En CSS puedes hacer la misma comprobación con @supports (field-sizing: content).

Qué vigilar

  • La especificación ha cambiado de sitio. field-sizing vive ahora en CSS Form Control Styling Level 1 (antes estaba en CSS UI 4). Ese borrador también define appearance: base y los controles de formulario que se pueden estilizar del todo, así que habrá más novedades por aquí.
  • Campos largos en diseños reales. Un campo que crece cambia el diseño que lo rodea. En flex y en grid no pasa nada, pero conviene poner siempre un max-width.
  • Quitar código viejo. Si tienes una dependencia o un hook cuyo único trabajo es ajustar el tamaño de los textarea, es buena candidata a desaparecer cuando tu público use navegadores de los últimos meses.

Fuentes