Os campos do formulário se ajustam automaticamente ao conteúdo

Recursos da Web: field-sizing

Por padrão, os controles de formulário, como <input>, <textarea> e <select>, têm dimensões fixas. Os tamanhos permanecem constantes, independentemente da quantidade de conteúdo que o usuário insere ou seleciona.

Para permitir que esses controles diminuam ou aumentem automaticamente para se ajustar ao conteúdo (incluindo marcadores de posição), use a propriedade CSS field-sizing: content.

Controles de formulário com dimensionamento automático

Definir field-sizing: content em entradas, seleções ou áreas de texto permite que elas sejam redimensionadas dinamicamente conforme o usuário digita ou seleciona opções. No entanto, é preciso considerar o estilo herdado, os padrões de layout e as restrições mínimas/máximas para garantir uma experiência do usuário robusta.

Para evitar problemas de layout, recomendamos definir min-inline-size (ou min-width) e max-inline-size (ou max-width) com field-sizing: content nas entradas de texto. Um tamanho mínimo impede que a entrada seja reduzida a uma largura de zero quando vazia (o que a torna não clicável), e um tamanho máximo garante que ela não se expanda indefinidamente e quebre o layout da página.

Para áreas de texto, permitir o dimensionamento automático horizontal pode causar uma UX desagradável (por exemplo, uma área de texto com um marcador de posição longo vai encolher abruptamente na horizontal quando o usuário digitar um único caractere). Para evitar isso, aplique uma largura explícita (como width: 100%) à área de texto. Isso força a área de texto a manter uma largura horizontal estável, enquanto o dimensionamento vertical é ajustado automaticamente conforme o conteúdo é quebrado.

Recomendamos definir um max-inline-size (ou max-width) em elementos <select> usando field-sizing: content para garantir que opções selecionadas extremamente longas não quebrem o layout da 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: as propriedades explícitas width e height substituem field-sizing: content em todos os controles de formulário. Se o CSS global do seu projeto definir entradas, seleções ou áreas de texto como width: 100%, será necessário redefini-las explicitamente como width: auto (ou width: fit-content) nos elementos que usam field-sizing: content para que o dimensionamento automático funcione. Por outro lado, defina explicitamente height: auto em áreas de texto se uma altura fixa tiver sido definida globalmente.

IMPORTANTE: os layouts de grade e Flexbox geralmente esticam os filhos de forma implícita para preencher o espaço disponível. Se algum controle de formulário que usa field-sizing: content não diminuir, verifique as propriedades de alinhamento do contêiner e aplique align-self: start ou justify-self: start ao controle de formulário para substituir o alongamento.

Estratégias de fallback

field-sizing precisa ser tratado como um aprimoramento progressivo. Em navegadores que não oferecem suporte à propriedade, os controles de formulário voltam ao comportamento padrão de dimensionamento fixo. Os usuários vão ter uma rolagem padrão para conteúdo que ultrapassa o limite em entradas e áreas de texto de tamanho fixo.

Se os campos de crescimento dinâmico forem absolutamente necessários para navegadores mais antigos, use a detecção de recursos e uma solução alternativa complexa. O substituto mais robusto para textareas usa um truque de grade CSS em que um pseudoelemento oculto espelha a entrada do usuário em tempo real, forçando o contêiner da grade (e a textarea dentro dele) a se expandir.

<!-- 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 a complexidade de duplicar estilos e sincronizar o estado entre nós do DOM para cada controle de formulário, confiar no comportamento de fallback padrão de entradas fixas é a abordagem recomendada para a maioria dos aplicativos, a menos que o dimensionamento dinâmico seja essencial para a experiência do usuário.