field-sizing

A property that lets `<textarea>`/`<input>` grow and shrink to fit their content with CSS alone.

Also known as: Auto-growing textareafield-sizing: content
···
html
<div class="wrap">
  <div class="badge" id="badge"><svg viewBox="0 0 10 10"><path id="bpath" d="M1.5 5.2l2.6 2.6L8.5 2.4" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg><span id="btext">확인 중</span></div>
  <textarea id="ta" class="ta" rows="1">메시지를 입력하면</textarea>
</div>
css
.wrap{position:relative;width:min(260px,92%)}
.ta{width:100%;min-height:38px;max-height:110px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;
  background:var(--surface);color:var(--fg);font-size:12px;font-family:inherit;resize:none;field-sizing:content;overflow-y:auto}
.ta.fallback{field-sizing:auto}
.badge{position:absolute;top:-30px;right:0;display:flex;align-items:center;gap:5px;padding:4px 9px;border-radius:999px;font-size:10px;font-weight:700;background:var(--bg);border:1px solid var(--line);color:var(--accent-3)}
.badge.no{color:var(--accent-2)}
.badge svg{width:9px;height:9px}
js
const ok = CSS.supports('field-sizing', 'content');
const b=document.getElementById('badge'),p=document.getElementById('bpath'),t=document.getElementById('btext');
b.classList.toggle('no', !ok);
p.setAttribute('d', ok ? 'M1.5 5.2l2.6 2.6L8.5 2.4' : 'M2 2l6 6M8 2l-6 6');
t.textContent = ok ? 'field-sizing 지원됨' : '미지원 · scrollHeight 폴백';
const ta = document.getElementById('ta');
if (!ok) {
  ta.classList.add('fallback');
  const resize = () => { ta.style.height = 'auto'; ta.style.height = ta.scrollHeight + 'px'; };
  ta.addEventListener('input', resize); resize();
}
const lines = ['메시지를 입력하면', '메시지를 입력하면\n자동으로 높이가', '메시지를 입력하면\n자동으로 높이가\n늘어납니다', '메시지를 입력하면'];
let i = 0;
setInterval(() => { i = (i+1) % lines.length; ta.value = lines[i]; ta.dispatchEvent(new Event('input')); }, 1600);

A textarea that grows as you type — like a chat input — has long been impossible without JS. `rows` only sets a fixed line count; growing to fit content required an input listener that reads `scrollHeight` and writes it back into `height` on every keystroke.

`field-sizing: content` makes a textarea or input follow its content size instead of an explicit `width`/`height`. Paired with `min-height`/`max-height`, "auto-grow up to 3 lines, then scroll" becomes pure CSS.

Check caniuse/MDN baseline for support. Without it, the classic auto-resize script — reading `scrollHeight` and writing `el.style.height` on every input event — is still needed.

When to use

Building a chat or comment input that auto-grows with its content, without JS.