فیلدهای فرم به‌طور خودکار با محتوا منطبق می‌شود

ویژگی‌های وب: 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 در ورودی‌های نوشتار تنظیم کنید. حداقل اندازه از جمع شدن ورودی به عرض صفر درصورت خالی بودن جلوگیری می‌کند (که باعث می‌شود غیرقابل‌کلیک شود)، و حداکثر اندازه تضمین می‌کند که به‌طور نامحدود گسترش نیابد و چیدمان صفحه را به‌هم نریزد.

برای textarea، مجاز کردن تغییر اندازه خودکار افقی می‌تواند باعث ایجاد تجربه کاربری ناخوشایند شود (برای مثال، textarea با جای‌بان طولانی وقتی کاربر یک نویسه تایپ می‌کند به‌طور ناگهانی به‌صورت افقی کوچک می‌شود). برای جلوگیری از این اتفاق، عرض صریحی (مانند width: 100%) را برای textarea اعمال کنید. This forces the textarea to maintain a stable horizontal width while still auto-sizing vertically as content wraps.

توصیه می‌شود 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 را به‌طور صریح در textareas تنظیم کنید.

مهم: چیدمان‌های Grid و Flexbox اغلب به‌طور ضمنی فرزندان خود را برای پر کردن فضای موجود گسترش می‌دهند. اگر هرکدام از کنترل‌های فرم که از field-sizing: content استفاده می‌کنند کوچک نمی‌شوند، ویژگی‌های تراز ظرف آن را بررسی کنید و align-self: start یا justify-self: start را روی کنترل فرم اعمال کنید تا کشیدگی لغو شود.

راهبردهای جایگزین

field-sizing باید به‌عنوان ارتقای پیش‌رو درنظر گرفته شود. در مرورگرهایی که از این ویژگی پشتیبانی نمی‌کنند، کنترل‌های فرم به‌طور متین به رفتار اندازه‌گذاری ثابت و پیش‌فرض خود تنزل می‌کنند. کاربران به‌سادگی پیمایش استاندارد را برای محتوای سرریز در ورودی‌ها و ناحیه‌های نوشتاری با اندازه ثابت تجربه خواهند کرد.

اگر فیلدهای درحال رشد پویا برای مرورگرهای قدیمی‌تر کاملاً ضروری است، باید از تشخیص ویژگی و راه‌حل پیچیده استفاده کنید. The most robust fallback for textareas uses a CSS Grid trick where a hidden pseudo-element mirrors the user's input in real-time, forcing the grid container (and the textarea inside it) to expand.

<!-- 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 برای هر کنترل فرم، تکیه بر رفتار بازگشتی پیش‌فرض ورودی‌های ثابت، رویکرد توصیه‌شده برای اکثر برنامه‌ها است، مگر اینکه اندازه‌گیری پویا برای تجربه کاربری حیاتی باشد.