طراحی Callout UI با CSS Offset و Border
خلاصهٔ کاملتر
یه Callout UI معمولاً از یه باکس متنی تشکیل میشه که یه خط راهنما (leader line) بهش وصله و به یه نقطهی خاص اشاره میکنه. این المان در لیاوتهای غیررسمی برای annotation و هایلایت بصری خیلی کاربرد داره. روشی که این مقاله معرفی میکنه کاملاً CSS-onlyه و از offset-path و border استفاده میکنه.
ساختار HTML سادهست: یه .callout بیرونی که .callout-text رو درخودش داره. المان بیرونی با container-type: size تبدیل به یه query container میشه تا بشه از واحدهای cqw و cqh برای موقعیتدهی دقیق استفاده کرد.
باکس متن با offset-path: border-box روی لبهی border والدش قرار میگیره. با offset-anchor: bottom نقطهی اتصال به پایین-مرکز باکس تغییر میکنه. بعد با offset-distance: 100cqw باکس متن دقیقاً به گوشهی بالا-راست میره — یعنی دورهی کامل عرض container:
.callout-text {
offset-path: border-box;
offset-anchor: bottom;
offset-distance: 100cqw;
}خط راهنما با ست کردن border راست و پایین .callout ساخته میشه. جالبترین مزیت این روش اینه که چون باکس متن به border وصله، هر تغییری در border — مثل skewX برای مایل کردن خط — روی موقعیت باکس هم اثر میذاره. برای打消 اثر skew روی متن، همون مقدار skew ولی با علامت عکس به .callout-text داده میشه.
علاوه بر border، میشه از box-shadow هم برای خط راهنما استفاده کرد تا جلوههای رنگی چندلایه ایجاد بشه. همچنین border-radius و ویژگی جدید corner-shape (مثل notch) شکل گوشههای خط رو تغییر میدن — و اگه مرورگر corner-shape رو پشتیبانی نکنه، به corner گرد fallback میشه.
این ساختار بهراحتی قابل انیمیشنه: ابتدا .callout با scaleY بهصورت عمودی باز میشه، بعد .callout-text با تأخیر کوچک scale میگیره. این ترتیب یه افکت روان و حرفهای میسازه که با hover فعال میشه.
نکات کلیدی:
offset-path: border-boxباکس متن رو روی لبهی border والد قرار میدهoffset-anchor: bottomنقطهی اتصال به offset path رو مشخص میکنهcontainer-type: sizeواحدcqwرو فعال میکنه تا بشه فاصلهی دقیق محاسبه کرد- skew روی callout برای مایل کردن خط، و skew معکوس روی متن برای خنثی کردن اثرش استفاده میشه
corner-shape: notchشکل گوشهی خط رو تغییر میده و با border-radius کار میکنه- کل طراحی انیمیشنپذیره و نیازی به جاوااسکریپت یا SVG نداره




