表單欄位自動調整成符合內容大小

網頁功能: field-sizing

根據預設,<input>、<textarea> 和 <select> 等表單控制項具有固定尺寸。無論使用者輸入或選取的內容多寡,大小都維持不變。

如要讓這些控制項自動縮小或放大,以符合內容 (包括預留位置),請使用 field-sizing: content CSS 屬性。

自動調整表單控制項大小

在輸入、選取或文字區域上設定 field-sizing: content,可讓這些區域在使用者輸入或選取選項時動態調整大小。不過,您必須考量繼承的樣式、版面配置預設值,以及大小限制,確保使用者體驗良好。

為避免版面配置問題,建議您在文字輸入欄位上同時設定 min-inline-size (或 min-width) 和 max-inline-size (或 max-width),以及 field-sizing: content。設定大小下限可避免輸入欄位在空白時寬度縮為零 (導致無法點選),設定大小上限則可確保欄位不會無限擴大,破壞頁面版面配置。

如果允許文字區域水平自動調整大小,可能會導致使用者體驗不佳 (例如,當使用者輸入單一字元時,含有長預留位置的文字區域會突然水平縮小)。為避免這種情況,請為文字區域套用明確的寬度 (例如 width: 100%)。這樣一來,文字區域就能維持穩定的水平寬度,同時在內容換行時自動調整垂直大小。

建議使用 field-sizing: content 在 <select> 元素上設定 max-inline-size (或 max-width),確保所選選項過長時不會破壞頁面版面配置。

/* 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;
}

重要事項:明確的 width 和 height 屬性會覆寫所有表單控制項上的 field-sizing: content。如果專案的全域 CSS 將輸入、選取或文字區域設為 width: 100%,您必須在使用 field-sizing: content 的元素上,明確將這些元素重設為 width: auto (或 width: fit-content),自動調整大小功能才能運作。相反地,如果先前已全域設定固定高度,則應在文字區域上明確設定 height: auto。

重要事項:格線和 Flexbox 版面配置通常會隱含地拉伸子項,填滿可用空間。如果使用 field-sizing: content 的表單控制項無法縮小,請檢查容器的對齊屬性,並將 align-self: start 或 justify-self: start 套用至表單控制項,覆寫拉伸效果。

備用策略

field-sizing 應視為漸進增強。在不支援該屬性的瀏覽器中,表單控制項會優雅降級,恢復為預設的固定大小行為。使用者在固定大小的輸入欄位和文字區域中,只會看到標準捲動效果。

如果舊版瀏覽器絕對需要動態成長欄位,則必須使用功能偵測和複雜的解決方法。最穩健的 textarea 備用方案是使用 CSS Grid 技巧,讓隱藏的虛擬元素即時反映使用者輸入內容,強制展開網格容器 (以及其中的 textarea)。

<!-- 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;
  }
}

由於複製樣式和同步處理每個表單控制項的 DOM 節點狀態相當複雜,因此除非動態調整大小對使用者體驗至關重要,否則建議大多數應用程式採用固定輸入的預設備用行為。