داستان از اونجایی شروع شد که بازی ای که مختص به تبلت زده بودم، میبایست رسپانسیو میشد
چالشی که وجود داشت موقعیت عناصر بود که بخاطر ماهیت بازی اکثرا absolute بودن و طبیعتا واحد ها همه پیکسل
کاری که من کردم دست نزدن به اعدد بود! بجاش تابعی درست کردم تا px رو به vmin تبدیل کنه و اینطوری کل پروژه مقیاس پذیر شد!
اگه نمیدونید رسپانسیو چی هست به این مقاله از سینا رضائی مراجعه کنید
اگه نمیدونید vw, vh, vmin چی هستن به این مقاله از css tricks مراجعه کنید
اگه با sass آشنایی ندارید به این مقاله از آرمان یه نگاهی بندازید
فلکس باکس ها و گرید ها خودشون موقعیت (position) هستن و برای لی اوت دادن به صفحه بکار میرن که موارد استفاده خودشون هم دارن
اما در این مقاله راجب حالتی صحبت میکنیم که موقیت عناصرتون از نوع absolute هست، مثلا بازی ها.
در این مواقع عنصرتون در اون نقطه ثابت میمونه حتی اگه صفحه کوچیک یا بزرگ بشه، که خب موجب ظاهر شدن اسکرول بارها میشه و با سایر بخش هایی که رسپانسیو هستن ناهماهنگی به وجود میاره
چارهی کار اینه که بجای استفاده از واحد هایی مثل پیکسل (px) از واحدهای تناسبی مثل vmin استفاده کنیم که خب مشکل حل میشه، کافیه در هنگام کدزدن بجای پیکسل از این واحد برای تمامی ویژگی هایی که میخواید به نسبت سایز طول و عرض صفحه واکنش پذیر باشه استفاده کنید.
اما مقدار دهی با این واحدهای تناسبی هم یه مشکلی داره اونم اینه که چون تناسبی هست نمیشه به طور دقیق به دستش آورد و مجوریم در صفحه با آزمون و خطا به اندازه دلخواهمون برسیم! خب ولی آیا میشه کاری کرد که هم بشه از خوبی های واحدهای تناسبی استفاده کرد هم از بدی هاش به دور بود؟
بله! کافیه به پیکسل طراحی کنید و این مقدار رو تو یه تابع مبدل بذارید، در ادامه این تابع رو معرفی میکنم تا ازش تو پروژه هاتون استفاده کنید.
خب شما تو پروژه تون پیکسل دارید و میخواید پیکسل هاتون رو نسبت به سایز صفحه نمایش مقیاس پذیر کنید، کافیه اون پروپرتی از استایلتون رو با این خط جایگزین کنین:
@include vmin("padding", 5px 10px);
همونطور که میبینید اگه قبلا padding: 5px 10px بود الان شد این
پس کاری که میکنید عنصرهای مدنظرتون رو با این جایگذاری میکنید، علاوه بر این باید خود تابع رو هم داخل فایلتون بذارید یا import کنید
تابع این هست:
$baseWidth: 1024px;
$baseHeight: 600px;
@function vw($px, $bw: $baseWidth) {
@return (100 * $px / $bw) * 1vw;
}
@function vh($px, $bh: $baseHeight) {
@return (100 * $px / $bh) * 1vh;
}
@mixin vmin($property, $pxs...) {
$vmin: null;
@each $px in $pxs {
$min: min(#{vh($px)}, #{vw($px)});
$vmin: $vmin $min;
}
#{$property}: $vmin;
}
در دو خط اول باید اندازه عرض و طول سایز صفحه نمایش پایه تون رو بنویسید چون پیکسل هاتون رو بر مبنای اون سایز زده بودید پس مبناتون اونها هستن و چیزی که الان میخواید باید به نسبت اون مبنا تولید بشن
خب تا اینجا کفایت میکنه ولی اگه خواستید تخصصی تر از این تابع استفاده کنید یا راجب نحوه ساخت تابع بدونید این بخش رو مطالعه کنید
میدونین vmin از واحدهای تناسبی css هست، هر vmin برابر کمترین مقدار بین طول و عرض نمایشگر هست، یعنی:
1vmin = min(1vh, 1vw)
این دو تا گزاره رو میشه جای هم بکار برد پس اگه vh و vw رو داشته باشیم با کمک min در css میتونیم vmin رو هم داشته باشیم
چیزی که ما در دست داریم، مقدار پیکسل و اندازه صفحه نمایشیه که این مقدار پیکسل رو برای اون سایز در نظر گرفته بودیم
پس ورودی هامون برای تابع: px, baseWith, baseHeight
و خروجی هامون: vh, vw هستن
به کمک نسبت و تناسب ها میشه به سادگی به فرمول تبدیل رسید، فرمول vw برابر میشه با:
اندازه عنصر (به px) تقسیم بر اندازه پایه (به px) = X (vw) تقسیم بر 100 (vw)
X = 100 * px / baseWith
که X مقدار تبدیل شده پیکسل ما به vh هست.
برای vh هم به همین صورته
در نهایت تابع ما به زبان scss به این صورت در میاد:
@function vw($px, $bw) {
@return (100 * $px / 1px / $bw) * 1vw;
}
برای vh هم به این صورت:
@function vh($px, $bh) {
@return (100 * $px / 1px / $bh) * 1vh;
}
حالا هر کجای scss مون این دو تابع رو فراخوانی کنیم و پیکسل بهش بدیم به ما مقادیر vh و vw میدن
برای مثال vw(100px, 1366) مقدار 7.3vw رو میده
و vh(100px, 768) مقدار 13vh رو میده
خب این تابع هامون که برای تولید vmin بهشون نیاز داریم، برای ساخت vmin هم کافیه اینها رو داخل min() بذاریم به اینصورت:
min(vw(100px, 1366), vh(100px, 768))
که البته در scss باید به این صورت نوشته و به عنصر تخصیص داده بشه
top: min(#{vw(100px, 1366), vh(100px, 768)});
خروجی های دو تابع در جای خودشون نوشته میشن و css کمترین ارزش بین 7.3vw و 13vw رو برای پروپرتی مدنظرمون در نظر میگیره
خب این از دو تابع و نحوه استفاده از اونها، اما جایگذاری این دو تابع در جای جای پروژه ممکنه کمی سخت باشه واسه همین میشه یه short hand براش به کمک mixin ها در scss نوشت که به کدهای بالا اضافه میشه، خودم در اکثر جاهای پروژه از این استفاده کردم:
$baseWidth: 1024px;
$baseHeight: 600px;
@mixin vmin($property, $pxs...) {
$vmin: null;
@each $px in $pxs {
$min: min(#{vh($px)}, #{vw($px)});
$vmin: $vmin $min;
}
#{$property}: $vmin;
}
که نحوه استفاده ازش هم به این صورته:
@include vmin("padding", 5px 10px);
خب این بود توضیح ریسپانسیوسازی مقیاسی و اینکه چطوری تمامی پیکسل های پروژه رو میشه به vmin تبدیل کرد، در پن زیر میتونید کدهاش رو یکجا و در عمل ببینید
در این مثال 5 نقطه قرمز مشاهده میکنید که همگی دارای موقعیت absolute هستن و طول، عرض و فاصلهشون از طرفین با واحد پیکسل تنظیم شده، میبینید که به چه خوبی واکنش گرا شدن
اگه نظر یا راه بهتری داشتید خوشحال میشم با من در میون بذارید.