Los campos del formulario se ajustan automáticamente al contenido

Funciones web: field-sizing

De forma predeterminada, los controles de formulario, como <input>, <textarea> y <select>, tienen dimensiones fijas. Sus tamaños permanecen constantes, independientemente de la cantidad de contenido que el usuario ingrese o seleccione.

Para permitir que estos controles se reduzcan o aumenten automáticamente para adaptarse a su contenido (incluidos los marcadores de posición), usa la propiedad de CSS field-sizing: content.

Controles de formulario con ajuste de tamaño automático

Si configuras field-sizing: content en las entradas, las selecciones o las áreas de texto, se les puede cambiar el tamaño de forma dinámica a medida que el usuario escribe o selecciona opciones. Sin embargo, debes tener en cuenta el estilo heredado, los valores predeterminados de diseño y las restricciones mínimas y máximas para garantizar una experiencia del usuario sólida.

Para evitar problemas de diseño, se recomienda establecer min-inline-size (o min-width) y max-inline-size (o max-width) junto con field-sizing: content en las entradas de texto. Un tamaño mínimo evita que la entrada se contraiga a un ancho de cero cuando está vacía (lo que impediría hacer clic en ella), y un tamaño máximo garantiza que no se expanda indefinidamente y rompa el diseño de la página.

En el caso de las áreas de texto, permitir el cambio de tamaño automático horizontal puede causar una UX desagradable (p.ej., un área de texto con un marcador de posición largo se reducirá de forma abrupta horizontalmente cuando el usuario escriba un solo carácter). Para evitarlo, aplica un ancho explícito (como width: 100%) al área de texto. Esto obliga al área de texto a mantener un ancho horizontal estable y, al mismo tiempo, cambiar de tamaño automáticamente de forma vertical a medida que se ajusta el contenido.

Se recomienda establecer un max-inline-size (o max-width) en los elementos <select> con field-sizing: content para garantizar que las opciones seleccionadas extremadamente largas no alteren el diseño de la página.

/* Applies horizontal auto-sizing to inputs */
input {
  /* Instructs the element to size itself to fit its content */
  field-sizing: content;

  /* Reset explicit width if inherited from global styles */
  width: auto;

  /* Prevents the input from collapsing and disappearing when empty */
  min-inline-size: 15ch;

  /* Prevents infinite horizontal growth */
  max-inline-size: 50ch;
}

textarea {
  /* Instructs the element to size itself to fit its content */
  field-sizing: content;

  /* Reset explicit height if inherited from global styles */
  height: auto;

  /* Use a fixed width to prevent jarring horizontal shifts when replacing a long placeholder */
  width: 50ch; /* or 100% depending on your layout */

  /* Sets a reasonable minimum height (e.g., 3 lines) for empty textareas */
  min-block-size: 3lh;

  /* Prevents infinite vertical growth. Once a textarea hits this */
  /* height, it will stop growing and show a vertical scrollbar. */
  max-block-size: 10lh;
}

select {
  /* Sizes the select element to fit the active option only */
  field-sizing: content;

  /* Prevents the dropdown from expanding infinitely and breaking the layout */
  max-inline-size: 50ch;
}

IMPORTANTE: Las propiedades explícitas width y height anulan field-sizing: content en todos los controles de formulario. Si el CSS global de tu proyecto establece entradas, selecciones o áreas de texto en width: 100%, debes restablecerlas de forma explícita a width: auto (o width: fit-content) en los elementos que usan field-sizing: content para que funcione el cambio de tamaño automático. Por el contrario, debes establecer explícitamente height: auto en las áreas de texto si se estableció previamente una altura fija de forma global.

IMPORTANTE: Los diseños de cuadrícula y Flexbox suelen estirar de forma implícita sus elementos secundarios para llenar el espacio disponible. Si algún control de formulario que use field-sizing: content se niega a reducirse, verifica las propiedades de alineación de su contenedor y aplica align-self: start o justify-self: start al control de formulario para anular el estiramiento.

Estrategias de resguardo

field-sizing se debe tratar como una mejora progresiva. En los navegadores que no admiten la propiedad, los controles de formulario se degradan de forma elegante a su comportamiento de tamaño fijo predeterminado. Los usuarios simplemente experimentarán el desplazamiento estándar para el contenido que se desborda dentro de las entradas y las áreas de texto de tamaño fijo.

Si los campos que crecen de forma dinámica son absolutamente necesarios para los navegadores más antiguos, debes usar la detección de funciones y una solución alternativa compleja. La alternativa más sólida para los elementos textarea usa un truco de cuadrícula de CSS en el que un pseudoelemento oculto refleja la entrada del usuario en tiempo real, lo que obliga al contenedor de la cuadrícula (y al elemento textarea que contiene) a expandirse.

<!-- The textarea is wrapped in a container that will mirror its value -->
<div class="growable-textarea" data-replicated-value="">
  <textarea></textarea>
</div>
// Only attach the fallback event listeners if field-sizing is unsupported
if (!CSS.supports('field-sizing', 'content')) {
  document.querySelectorAll('.growable-textarea > textarea').forEach(textarea => {
    textarea.addEventListener('input', () => {
      textarea.parentNode.dataset.replicatedValue = textarea.value;
    });
  });
}
/* Only apply the fallback if field-sizing is NOT supported */
@supports not (field-sizing: content) {
  .growable-textarea {
    display: grid;
  }

  /* The pseudo-element and textarea must share the exact same cell, font, and padding */
  .growable-textarea::after,
  .growable-textarea > textarea {
    grid-area: 1 / 1 / 2 / 2;
    font: inherit;
    padding: 0.5rem;
    border: 1px solid #999;
  }

  /* The pseudo-element renders the copied text invisibly to stretch the grid */
  .growable-textarea::after {
    /* The space is necessary for trailing empty lines to be rendered */
    content: attr(data-replicated-value) " ";
    white-space: pre-wrap;
    visibility: hidden;
  }

  .growable-textarea > textarea {
    resize: none;
    overflow: hidden;
  }
}

Dada la complejidad de duplicar estilos y sincronizar el estado en los nodos del DOM para cada control de formulario, el enfoque recomendado para la mayoría de las aplicaciones es confiar en el comportamiento de resguardo predeterminado de las entradas fijas, a menos que el tamaño dinámico sea fundamental para la experiencia del usuario.