شعاع مرز شرطی در CSS

استاد چیدمان
چندی پیش فیدهای صفحه اصلی facebook.com را بررسی می کردم تا یاد بگیرم و ببینم که آنها چگونه چیزها را می سازند. من همیشه کنجکاو هستم که ببینم مردم چگونه CSS می نویسند. متوجه شدم خیلی خیلی جالب بود border-radius مقدار برای مؤلفه نقشه در کانال اصلی.
موارد زیر را به اشتراک گذاشتم یک توییت برای این کشف کوچک بعد گرفتم این پاسخ توسط میریام سوزان:
آیا همیشه 8 پیکسل است؟ این ریاضی به نظر من مانند یک ضامن است که در آن در نقطه ای ((100vw – 4px) – 100%) می تواند منفی باشد و 9999 را به -9999 تغییر دهید؟ کدام مقدار را به 0 معکوس می کند؟ اساساً: اگر در فاصله 4 پیکسلی از اندازه کامل ویوپورت هستیم، شعاع مرزی را حذف کنید.
چند ساعت دیگر، فرانک جان از فیس بوک (هورای!) تایید شد که یک معکوس مشروط است 8px به 0px زمانی که نقشه کل عرض نمای را اشغال می کند.
آیا این فقط شگفت انگیز نیست؟
در ابتدا فکر کردم که این نوعی باگ یا چیزی است که به اشتباه انجام شده است. خوشبختانه اشتباه کردم. در این مقاله سعی می کنم مشکل را برجسته کنم و نحوه کار راه حل ها را توضیح دهم.
مشکل
ما یک جزء نقشه با a داریم border-radius در 8px. زمانی که نقشه هیچ حاشیه ای ندارد یا کل عرض نمای را اشغال می کند، می خواهیم ورق بزنیم border-radius به 0.

این را می توان با حذف کردن انجام داد border-radius با یک پرس و جو رسانه CSS مانند این.
@media (min-width: 700px) {
.card {
border-radius: 8px;
}
}
در برخی موارد، این محدودیت است. اگر به دلایلی بخواهیم فعال کنیم border-radius زمانی که اندازه ی ویوپورت کمتر از 450px، باید یک تغییر کلاس CSS ایجاد کنیم و دوباره از یک درخواست رسانه استفاده کنیم.
@media (max-width: 450px) {
.card--rounded {
border-radius: 8px;
}
}
راه حل
این کار هوشمندانه ای است که توسط تیم فیس بوک انجام شده است. منطق زیر را شبیه سازی می کند:
if (cardWidth >= viewportWidth) {
radius = 0;
} else {
radius = 8px;
}
برای پیاده سازی این منطق در CSS، باید دو مقدار را با استفاده از توابع مقایسه CSS مقایسه کنیم. اگر آنها را نمی شناسید، خواندن این مقاله شما را توصیه می کنم.
راه حل از مقاله The Flexbox Holy Albatross اثر Heydon Pickering الهام گرفته شده است. از اقتباس شده است نامان گوئل از فیس بوک برای کار border-radius.
.card {
border-radius: max(
0px,
min(8px, calc((100vw - 4px - 100%) * 9999))
);
}
بیایید نگاهی دقیق به CSS بالا بیندازیم.
- یک داریم
max()تابعی که بین0pxو مقدار محاسبه شده ازmin(). مقدار بزرگتر را انتخاب می کند. - را
min()تابع مقایسه بین8pxو مقدار محاسبه شده ازcalc((100vw - 4px - 100%) * 9999). این به یک عدد مثبت یا منفی بسیار بزرگ منجر می شود. - را
9999یک عدد بزرگ است که مقدار را مجبور می کند یکی از این دو باشد0pxیا8px.
اجازه بدهید توضیح دهیم calc() جادو!
جادو در اتفاق می افتد 100% ارزش بر اساس دو سناریو متفاوت می تواند متفاوت باشد:
- می تواند برابر باشد
100%عنصر حاوی (Parent/wrapper.. یا هر چیزی که در CSS شما نامیده می شود). - یا می تواند برابر باشد
100vw، در صورتی که نقشه کل عرض درگاه دید را اشغال کند (به عنوان مثال: در یک دستگاه تلفن همراه).

چرا استفاده کنید 9999?
دلیلش این نیست که آن عدد خاص یک ابرقدرت یا هر چیز دیگری دارد. این در مورد اجتناب از یک مورد شدید است. با تشکر از تمنی عفیف برای یادآوری این موضوع
فرض کنید عرض نمای ویوپورت باشد 375px، و ظرف است 365px. اگر این مقادیر را جایگزین معادله کنیم، به این صورت خواهد بود.
.card {
border-radius: max(0px, min(8px, calc(375px - 4px - 365px)));
border-radius: max(0px, min(8px, 6px));
}
بر اساس مقدار فوق 6px توسط مرورگر انتخاب خواهد شد. ما این را نمی خواهیم. در عوض، شعاع باید یکی باشد 0px یا 8px. برای رسیدن به این هدف، میتوانیم نتیجه را در عدد بزرگی ضرب کنیم که احتمال استفاده از آن در CSS کمتر است 9999.
.card {
border-radius: max(
0px,
min(8px, calc((375px - 4px - 365px) * 9999))
);
border-radius: max(0px, min(8px, 59994px));
}
بر این اساس مرورگر انتخاب خواهد کرد 8px از تابع min و سپس همان مقدار از max() تابع
بیایید بر اساس سناریوی اول مثالی بزنیم. ما یک viewport با عرض داریم 1440pxو جزء نقشه در a زندگی می کند 700px ظرف

مقدار حاصل را در ضرب کنید 9999 منجر خواهد شد 7359264، که یک عدد تصادفی بزرگ است. در این مورد، CSS برای مرورگر به شکل زیر خواهد بود:
.card {
border-radius: max(0px, min(8px, 7359264px));
}
از آنجایی که داریم min()، انتخاب خواهد کرد کوچکترین ارزش است 8px. در مقایسه با max()، در 8px نیز برنده خواهد شد. این اولین مورد استفاده از این CSS هوشمند است.
.card {
border-radius: 8px;
}
پس از آن زمانی است که نقشه کل عرض نمای را اشغال می کند. این را می توان در نمای موبایل مشاهده کرد. توجه داشته باشید که عرض کانتینر و viewport یکسان است.

ضرب مقدار در 9999 منجر خواهد شد -39996px، که یک است ارزش منفی. مرورگر آن را به صورت زیر می خواند:
.card {
border-radius: max(0px, min(8px, -39996px));
}
حالا برای سرگرمی! مرورگر باید دو سوال بپرسد:
- کدام مقدار کوچکتر است؟
8pxیا-39996px? نتیجه این است-39996px. - کدام ارزش بیشتر است؟
0pxیا-39996px? نتیجه این است0px.
.card {
border-radius: 0px;
}
دیدی چطور شد؟ من هنوز از چنین استفاده هوشمندانه از ویژگی های CSS برای مقایسه شگفت زده هستم.
همچنین می توانیم با استفاده از CSS این را به سطح بعدی برسانیم clamp() همانطور که توسط تمنی عفیف و لیاد یوسف. من فکر می کنم تیم فیس بوک از آن استفاده نکرده است زیرا در نسخه های قدیمی سافاری (به عنوان مثال: v12) پشتیبانی نمی شود.
.card {
border-radius: clamp(0px, ((100vw - 4px) - 100%) * 9999, 8px);
}
آن را در Codepen بررسی کنید.
امیدوارم مقاله را دوست داشته باشید. با تشکر برای خواندن!

