aspect-ratio؛ دیگه نیازی به تریک padding-top نیست

اگه قبلاً خواسته باشید یه باکس با نسبت ابعاد ثابت بسازید (مثلاً یه ویدیو ۱۶:۹ یا یه عکس مربعی)، احتمالاً با اون تریک قدیمی و کمی عجیب padding-top: 56.25%; روبه‌رو شدید؛ روشی که از نسبت پدینگ به عرض المنت سوءاستفاده می‌کرد تا یه ارتفاع نسبی بسازه. خوشبختانه الان یه راه مستقیم و ساده برای این کار داریم: ویژگی aspect-ratio.

مشکل قدیمی: چرا نمی‌شد مستقیم ارتفاع رو نسبت به عرض تعریف کرد؟

تو CSS سنتی، هیچ راهی برای گفتن «ارتفاع این المنت باید همیشه ۵۶٪ عرضش باشه» وجود نداشت، چون height و width کاملاً مستقل از هم محاسبه می‌شدن. به همین خاطر توسعه‌دهنده‌ها مجبور بودن از رفتار خاص padding-top درصدی (که همیشه نسبت به عرض والد حساب می‌شه، حتی وقتی روی محور عمودیه) به‌عنوان یه دور زدن هوشمندانه استفاده کنن.

سینتکس ساده‌ی aspect-ratio

.video {
  aspect-ratio: 16 / 9;
  width: 100%;
}

همین. با این دو خط، عرض المنت هر چقدر باشه (چون width: 100% گذاشتیم)، ارتفاعش خودکار طوری محاسبه می‌شه که نسبت ۱۶ به ۹ حفظ بشه. دیگه نیازی به هیچ پدینگ عجیبی، هیچ المنت wrapper اضافه‌ای، و هیچ محاسبه‌ی دستی نیست.

مقادیر قابل قبول

روش نوشتنمثال
دو عدد با اسلشaspect-ratio: 16 / 9;
یه عدد تنهاaspect-ratio: 1.777;
نسبت ساده (مربع)aspect-ratio: 1 / 1;
autoaspect-ratio: auto; (پیش‌فرض؛ بدون محدودیت)

وقتی فقط یه عدد تنها می‌نویسید (مثل 1.777)، مرورگر اون رو به‌عنوان نسبت عرض به ارتفاع در نظر می‌گیره؛ یعنی معادل 1.777 / 1.

کاربرد رایج: تصاویر با نسبت ثابت، صرف‌نظر از سایز اصلی فایل

یکی از کاربردهای خیلی رایج aspect-ratio، یکدست کردن سایز عکس‌هایی هست که از سرور با ابعاد مختلف میان (مثلاً تو یه گرید گالری):

.gallery img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

اینجا ترکیب aspect-ratio با object-fit: cover خیلی مهمه: aspect-ratio قاب رو به شکل ۴:۳ نگه می‌داره، ولی چون عکس اصلی ممکنه نسبت متفاوتی داشته باشه، object-fit: cover تضمین می‌کنه که عکس بدون کش اومدن یا خالی موندن فضا، دقیقاً همون قاب رو پر کنه (با کراپ شدن لبه‌ها در صورت نیاز).

کاربرد دیگه: نگه‌داشتن جای ویدیو یا iframe قبل از لود شدن

یه مشکل رایج تو صفحات وب، «پرش چیدمان» (layout shift) هست: وقتی یه ویدیو یا iframe هنوز لود نشده، فضایی براش در نظر گرفته نمی‌شه، و به محض لود شدن، محتوای اطرافش ناگهان جابه‌جا می‌شه. با aspect-ratio می‌شه از قبل، حتی قبل از این‌که محتوا لود بشه، فضای دقیق رو رزرو کرد:

iframe {
  width: 100%;
  aspect-ratio: 16 / 9;
  border: none;
}

وقتی هم width هم height مشخص شده باشن، چه اتفاقی می‌افته؟

اگه یه المنت هم width و هم height رو صریحاً تعریف کرده باشه (نه فقط یکی)، aspect-ratio نادیده گرفته می‌شه، چون هر دو بعد از قبل مشخص شدن و دیگه چیزی برای محاسبه‌ی خودکار باقی نمی‌مونه. aspect-ratio فقط زمانی وارد عمل می‌شه که یکی از این دو (معمولاً height) نامشخص یا auto باشه.

نکته مهم: اگه هم aspect-ratio و هم محتوای داخلی المنت باعث بشن ارتفاع لازم بیشتر از چیزی باشه که نسبت تعیین می‌کنه (مثلاً یه متن طولانی که جا نمی‌شه)، به‌طور پیش‌فرض محتوا اولویت داره و ممکنه از قاب بیرون بزنه. برای جلوگیری از این، معمولاً overflow: hidden هم به کار می‌بندن.

اشتباه رایج: استفاده از aspect-ratio روی المنتی که هم عرض و هم ارتفاعش از قبل fixed هست

خیلی‌ها aspect-ratio رو اضافه می‌کنن ولی فراموش می‌کنن که یه height ثابت (مثلاً از یه استایل قدیمی‌تر یا فریم‌ورک) هنوز روی همون المنت مونده. تو این حالت، چون هر دو بعد مشخصه، aspect-ratio عملاً بی‌اثر می‌مونه و نتیجه‌ی موردنظر گرفته نمی‌شه. همیشه قبل از استفاده از aspect-ratio، مطمئن بشید height رو صریح تنظیم نکرده باشید (یا auto باشه).

جمع‌بندی

aspect-ratio یه راه ساده و مستقیم برای نگه‌داشتن نسبت عرض به ارتفاع یه المنته، بدون نیاز به تریک‌های قدیمی padding. کاربرد اصلیش تو تصاویر، ویدیوها و iframe هاست، جایی که هم می‌خواید نسبت ابعاد حفظ بشه، هم از پرش چیدمان قبل از لود محتوا جلوگیری کنید. فقط یادتون باشه که اگه height صریح تنظیم شده باشه، این ویژگی بی‌اثر می‌مونه.