ช่องแบบฟอร์มจะปรับให้พอดีกับเนื้อหาโดยอัตโนมัติ

ฟีเจอร์เว็บ: field-sizing

โดยค่าเริ่มต้น ตัวควบคุมแบบฟอร์ม เช่น <input>, <textarea> และ <select> จะมีขนาดคงที่ ขนาดของช่องจะคงที่ ไม่ว่าผู้ใช้จะป้อนหรือเลือกเนื้อหามากน้อยเพียงใดก็ตาม

หากต้องการอนุญาตให้ตัวควบคุมเหล่านี้ย่อหรือขยายโดยอัตโนมัติเพื่อให้พอดีกับเนื้อหา (รวมถึงตัวยึดตำแหน่ง) ให้ใช้พร็อพเพอร์ตี้ CSS field-sizing: content

การควบคุมแบบฟอร์มการปรับขนาดอัตโนมัติ

การตั้งค่า field-sizing: content ในอินพุต, ตัวเลือก หรือพื้นที่ข้อความช่วยให้ปรับขนาดแบบไดนามิกได้เมื่อผู้ใช้พิมพ์หรือเลือกตัวเลือก อย่างไรก็ตาม คุณต้องพิจารณาการจัดรูปแบบที่รับค่ามา ค่าเริ่มต้นของเลย์เอาต์ และการจำกัดขั้นต่ำ/สูงสุดเพื่อให้ผู้ใช้ได้รับประสบการณ์ของผู้ใช้ที่มีประสิทธิภาพ

เพื่อป้องกันปัญหาเกี่ยวกับเลย์เอาต์ เราขอแนะนำให้ตั้งค่าทั้ง min-inline-size (หรือ min-width) และ max-inline-size (หรือ max-width) ควบคู่ไปกับ field-sizing: content ในการป้อนข้อความ ขนาดขั้นต่ำจะป้องกันไม่ให้ช่องป้อนข้อมูลยุบลงจนมีความกว้างเป็น 0 เมื่อว่างเปล่า (ทำให้คลิกไม่ได้) และขนาดสูงสุดจะช่วยให้มั่นใจได้ว่าช่องป้อนข้อมูลจะไม่ขยายออกไปเรื่อยๆ จนทำให้เลย์เอาต์ของหน้าเสีย

สำหรับ textarea การอนุญาตให้ปรับขนาดอัตโนมัติในแนวนอนอาจทำให้ UX ไม่ราบรื่น (เช่น textarea ที่มีตัวยึดตำแหน่งยาวจะหดตัวในแนวนอนอย่างกะทันหันเมื่อผู้ใช้พิมพ์อักขระเพียงตัวเดียว) หากต้องการป้องกันปัญหานี้ ให้ใช้ความกว้างที่ชัดเจน (เช่น width: 100%) กับ textarea ซึ่งจะบังคับให้ textarea คงความกว้างแนวนอนที่คงที่ไว้ขณะที่ยังคงปรับขนาดแนวตั้งโดยอัตโนมัติเมื่อเนื้อหาตัดขึ้นบรรทัดใหม่

ขอแนะนำให้ตั้งค่า max-inline-size (หรือ max-width) ในองค์ประกอบ <select> โดยใช้ field-sizing: content เพื่อให้แน่ใจว่าตัวเลือกที่เลือกซึ่งมีความยาวมากจะไม่ทำให้เลย์เอาต์ของหน้าเสียหาย

/* 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% คุณต้องรีเซ็ตเป็น width: auto (หรือ width: fit-content) อย่างชัดเจนในองค์ประกอบที่ใช้ field-sizing: content เพื่อให้การปรับขนาดอัตโนมัติทำงาน ในทางกลับกัน คุณควรตั้งค่า height: auto ใน textarea อย่างชัดเจนหากก่อนหน้านี้มีการตั้งค่าความสูงคงที่ไว้ทั่วโลก

สำคัญ: เลย์เอาต์แบบตารางกริดและ Flexbox มักจะยืดองค์ประกอบย่อยโดยนัยเพื่อเติมพื้นที่ว่างที่มีอยู่ หากตัวควบคุมแบบฟอร์มที่ใช้ field-sizing: content ไม่ยอมหด ให้ตรวจสอบพร็อพเพอร์ตี้การจัดแนวของคอนเทนเนอร์และใช้ align-self: start หรือ justify-self: start กับตัวควบคุมแบบฟอร์มเพื่อลบล้างการยืด

กลยุทธ์สำรอง

ควรใช้ field-sizing เป็นการเพิ่มประสิทธิภาพแบบต่อเนื่อง ในเบราว์เซอร์ที่ไม่รองรับพร็อพเพอร์ตี้นี้ ตัวควบคุมแบบฟอร์มจะลดลงอย่างค่อยเป็นค่อยไปกลับไปเป็นลักษณะการทำงานของการปรับขนาดคงที่ตามค่าเริ่มต้น ผู้ใช้จะเห็นการเลื่อนแบบมาตรฐานสำหรับเนื้อหาที่ล้นภายในอินพุตและ textarea ที่มีขนาดคงที่

หากจำเป็นต้องใช้ช่องที่ขยายแบบไดนามิกสำหรับเบราว์เซอร์รุ่นเก่า คุณต้องใช้การตรวจหาฟีเจอร์และวิธีแก้ปัญหาที่ซับซ้อน ทางเลือกสำรองที่มีประสิทธิภาพที่สุดสำหรับ textarea ใช้เคล็ดลับ CSS Grid โดยที่องค์ประกอบจำลองที่ซ่อนอยู่จะแสดงอินพุตของผู้ใช้แบบเรียลไทม์ ซึ่งจะบังคับให้คอนเทนเนอร์ 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 สำหรับการควบคุมแบบฟอร์มทุกรายการ การใช้ลักษณะการทำงานสำรองเริ่มต้นของอินพุตแบบคงที่จึงเป็นแนวทางที่แนะนำสำหรับแอปพลิเคชันส่วนใหญ่ เว้นแต่ว่าการปรับขนาดแบบไดนามิกจะมีความสำคัญต่อประสบการณ์ของผู้ใช้