ساخت چیدمان کاملاً سیال: Fluid Layout و Fluid Typography با clamp()

در درس قبل، Fluid Typography رو در کنار رویکرد پلکانی دیدیم. حالا وقتشه یک قدم فراتر بریم و ببینیم چطور می‌شه، نه فقط اندازه فونت، بلکه کل چیدمان یک صفحه (فاصله‌گذاری، عرض عناصر، حتی Padding و Gap) رو، با همون فلسفه clamp()، کاملاً سیال و بدون نیاز به Breakpointهای پرشی، طراحی کرد.

یادآوری سریع: clamp()

.box {
  width: clamp(300px, 50vw, 800px);
}

همون‌طور که در فصل‌های قبل دیدیم، clamp(min, preferred, max)، یک مقدار رو بین یک حداقل و حداکثر مشخص، به‌طور پیوسته، بر اساس یک مقدار وسط (که معمولاً شامل یک واحد Viewport مثل vw است)، محاسبه می‌کنه.

چرا Fluid Layout؟

در رویکرد سنتی Breakpoint، عرض یا فاصله‌گذاری یک عنصر، در هر Breakpoint، یک «پرش» ناگهانی می‌کنه؛ مثلاً Padding از ۱۶ پیکسل، ناگهان به ۳۲ پیکسل تبدیل می‌شه. با Fluid Layout، این تغییر، به‌جای پرش، به‌طور نرم و تدریجی، همراه با تغییر عرض صفحه، اتفاق می‌افته.

Fluid Padding و Spacing

.container {
  padding-inline: clamp(16px, 5vw, 64px);
}

در این مثال، Padding افقی Container، هیچ‌وقت از ۱۶ پیکسل کمتر و از ۶۴ پیکسل بیشتر نمی‌شه؛ ولی بین این دو، با تغییر عرض صفحه، به‌طور کاملاً نرم، افزایش یا کاهش پیدا می‌کنه؛ بدون هیچ Media Query‌ای.

Fluid Gap در Flexbox و Grid

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: clamp(12px, 3vw, 32px);
}

دقیقاً همون منطق، برای gap که در فصل ۱۲ و ۱۳ دیدیم هم قابل‌اعماله؛ فاصله بین کارت‌ها، متناسب با فضای موجود، به‌طور نرم رشد می‌کنه. این ترکیب، همراه با auto-fit که در فصل ۱۳ دیدیم، یک Grid کاملاً واکنش‌گرا می‌سازه که هم تعداد ستون‌ها و هم فاصله بین‌شون، بدون هیچ Media Query‌ای، خودشون رو با صفحه تطبیق می‌دن.

Fluid Width با محدودیت‌های منطقی

.article {
  width: clamp(300px, 90%, 700px);
}

در این مثال، عرض مقاله، هیچ‌وقت از ۳۰۰ پیکسل کوچک‌تر یا از ۷۰۰ پیکسل بزرگ‌تر نمی‌شه؛ در حالت میانی، ۹۰٪ عرض والدش رو می‌گیره. این الگو، جایگزین بسیار روان‌تری برای ترکیب سنتی width: 90%; max-width: 700px; است؛ چون هر دو محدودیت (حداقل و حداکثر) رو، در یک خط، هم‌زمان مدیریت می‌کنه.

ترکیب Fluid Typography و Fluid Layout در یک کامپوننت واحد

.hero {
  padding-block: clamp(40px, 10vw, 120px);
  padding-inline: clamp(16px, 5vw, 64px);
}

.hero h1 {
  font-size: clamp(2rem, 6vw, 4.5rem);
  line-height: 1.1;
}

.hero p {
  font-size: clamp(1rem, 2vw, 1.25rem);
  max-width: 60ch;
}

در این مثال، هر جنبه از یک بخش Hero (فاصله‌گذاری بالا/پایین، فاصله‌گذاری چپ/راست، اندازه تیتر، و اندازه متن توضیحی)، همگی، به‌طور مستقل، اما هماهنگ، با clamp() تعریف شدن؛ نتیجه، یک بخش کاملاً سیاله که در هر عرضی، از کوچک‌ترین موبایل تا بزرگ‌ترین مانیتور، به‌طور طبیعی و بدون هیچ پرش ناگهانی، ظاهر متناسبی داره.

یک فرمول عملی برای انتخاب مقدار وسط clamp()

یکی از سؤالات رایج، اینه که مقدار وسط (Preferred Value) در clamp() رو، چطور باید انتخاب کرد. یک روش عملی و رایج، استفاده از این فرمول تقریبیه:

مقدار وسط = عدد کوچک (برای شیب ملایم) × vw + یک مقدار پایه با rem
h1 {
  font-size: clamp(2rem, 1rem + 3vw, 3.5rem);
}

ترکیب vw با rem، همون‌طور که در فصل ۸ دیدیم، هم باعث انعطاف‌پذیری نسبت به عرض صفحه می‌شه، و هم، به‌خاطر بخش rem، همچنان تا حدی به تنظیمات دسترسی‌پذیری کاربر (بزرگ‌نمایی فونت) واکنش نشون می‌ده.

چه زمانی Fluid Layout کافی نیست و باز هم به Media Query نیاز داریم؟

.nav {
  display: flex;
  flex-direction: column;
}

@media (min-width: 700px) {
  .nav {
    flex-direction: row;
  }
}

Fluid Layout، برای تغییرات پیوسته (مثل اندازه، فاصله، عرض) عالیه؛ ولی برای تغییرات ساختاری و گسسته (مثل تغییر جهت Flexbox از ستونی به افقی، یا تغییر تعداد دقیق ستون‌های یک Grid با grid-template-areas که در فصل ۱۳ دیدیم)، همچنان به Media Query نیاز داریم؛ چون این نوع تغییرات، ماهیتاً «یا این یا اون» هستن، نه یک طیف پیوسته.

جدول جمع‌بندی: کجا از کدام ابزار استفاده کنیم

نوع تغییر ابزار مناسب
اندازه فونت، Padding، Gap، عرض clamp() (Fluid)
تغییر جهت Flexbox، تعداد دقیق ستون Grid، نمایش/عدم‌نمایش یک عنصر Media Query (پلکانی)
تعداد ستون‌های خودکار در Grid auto-fit/auto-fill (بدون نیاز به هیچکدام)

نکات مهم

  • Fluid Layout، با استفاده از clamp() روی Padding، Gap و عرض عناصر، تغییرات نرم و پیوسته‌ای ایجاد می‌کند که نیاز به Breakpointهای پرشی را کاهش می‌دهد.
  • ترکیب vw و rem در مقدار وسط clamp()، هم انعطاف‌پذیری نسبت به عرض صفحه و هم پاسخگویی به تنظیمات دسترسی‌پذیری کاربر را حفظ می‌کند.
  • Fluid Layout، جایگزین کامل Media Query نیست؛ برای تغییرات ساختاری و گسسته (مثل جهت Flexbox)، همچنان به Media Query نیاز داریم.

اشتباهات رایج

  • تلاش برای جایگزین کردن تمام Media Queryها با clamp()، حتی برای تغییرات ساختاری که ماهیتاً گسسته‌اند، نه پیوسته.
  • انتخاب حداقل و حداکثر نامناسب در clamp()، که می‌تواند در عرض‌های خیلی کوچک یا خیلی بزرگ، ظاهر نامتناسبی ایجاد کند.
  • فراموش کردن تست عملی مقادیر clamp() در عرض‌های میانی، نه فقط در حداقل و حداکثر.

جمع‌بندی

Fluid Layout، با استفاده از تابع clamp() روی Propertyهایی مثل Padding، Gap، عرض و اندازه فونت، امکان ساخت چیدمان‌هایی رو فراهم می‌کند که به‌طور نرم و پیوسته، بدون پرش‌های ناگهانی Breakpoint، با هر عرض صفحه‌نمایشی هماهنگ می‌شوند. این رویکرد، مکمل Media Query است، نه جایگزین کامل آن؛ برای تغییرات ساختاری و گسسته، همچنان از Media Query استفاده می‌شود، در حالی که برای تغییرات پیوسته اندازه و فاصله، clamp() ابزار روان‌تر و ساده‌تری است.