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.