قابلیتهای پیشرفته CSS را با @property، ویژگی قدرتمند ثبت و سفارشیسازی پراپرتیهای CSS، باز کنید. یاد بگیرید چگونه از آن برای استایلدهی و کنترل انیمیشن پیشرفته استفاده کنید.
تسلط بر CSS: ثبت پراپرتیهای سفارشی با @property
پراپرتیهای سفارشی (که به عنوان متغیرهای CSS نیز شناخته میشوند) نحوه نوشتن و نگهداری CSS را متحول کردهاند. آنها به ما امکان میدهند مقادیر قابل استفاده مجدد را تعریف کنیم و استایلشیتهای ما را انعطافپذیرتر و قابل نگهداریتر میکنند. اما اگر بتوانید فراتر از تعریف ساده مقادیر بروید چه؟ اگر بتوانید نوع مقداری که یک پراپرتی سفارشی نگه میدارد، به همراه مقدار اولیه و رفتار وراثت آن را تعریف کنید چه؟ اینجاست که @property وارد میشود.
@property چیست؟
@property یک at-rule در CSS است که به شما امکان میدهد یک پراپرتی سفارشی را به صراحت در مرورگر ثبت کنید. این فرآیند ثبت، اطلاعاتی در مورد نوع مورد انتظار پراپرتی، مقدار اولیه آن و اینکه آیا باید از عنصر والد خود به ارث ببرد یا خیر، در اختیار مرورگر قرار میدهد. این امر چندین قابلیت پیشرفته را باز میکند، از جمله:
- بررسی نوع (Type checking): اطمینان حاصل میکند که به پراپرتی سفارشی، مقداری از نوع صحیح اختصاص داده شده است.
- انیمیشن: امکان انتقالها و انیمیشنهای روان را برای پراپرتیهای سفارشی با انواع خاص، مانند اعداد یا رنگها، فراهم میکند.
- مقادیر پیشفرض: در صورتی که پراپرتی سفارشی به صراحت تعریف نشده باشد، یک مقدار جایگزین (fallback) ارائه میدهد.
- کنترل وراثت: تعیین میکند که آیا پراپرتی سفارشی مقدار خود را از عنصر والد خود به ارث میبرد یا خیر.
به آن مانند افزودن ایمنی نوع (type safety) به متغیرهای CSS خود فکر کنید. این به شما امکان میدهد استایلشیتهای قویتر و قابل پیشبینیتری ایجاد کنید.
سینتکس @property
قانون @property از این سینتکس پایه پیروی میکند:
@property --property-name {
syntax: '';
inherits: true | false;
initial-value: ;
}
بیایید هر بخش را بررسی کنیم:
--property-name: نام پراپرتی سفارشی که میخواهید ثبت کنید. باید با دو خط تیره (--) شروع شود.syntax: نوع مقدار مورد انتظار برای پراپرتی را تعریف میکند. این بخش برای بررسی نوع و انیمیشن بسیار مهم است. در ادامه مقادیر موجود برای سینتکس را به تفصیل بررسی خواهیم کرد.inherits: یک مقدار بولین (boolean) که نشان میدهد آیا پراپرتی باید از عنصر والد خود به ارث ببرد یا خیر. در صورت مشخص نشدن، پیشفرض آنfalseاست.initial-value: مقدار پیشفرض برای پراپرتی در صورتی که به صراحت روی یک عنصر تنظیم نشده باشد. این امر تضمین میکند که یک مقدار جایگزین همیشه در دسترس است.
درک توصیفگر syntax
توصیفگر syntax مهمترین بخش قانون @property است. این به مرورگر میگوید چه نوع مقداری را برای پراپرتی سفارشی انتظار داشته باشد. در اینجا برخی از مقادیر رایج سینتکس آورده شده است:
*: به هر مقداری اجازه میدهد. این منعطفترین سینتکس است و اساساً رفتار یک متغیر CSS استاندارد بدون ثبت را تکرار میکند. از این مورد با احتیاط استفاده کنید.<length>: یک مقدار طول (مانند10px,2em,50%) انتظار دارد. این امکان انیمیشنهای روان بین مقادیر مختلف طول را فراهم میکند.<number>: یک مقدار عددی (مانند1,3.14,-5) انتظار دارد. برای انیمیشن کردن پراپرتیهای عددی مانند شفافیت (opacity) یا مقیاس (scale) مفید است.<percentage>: یک مقدار درصدی (مانند25%,100%) انتظار دارد.<color>: یک مقدار رنگ (مانند#f00,rgb(255, 0, 0),hsl(0, 100%, 50%)) انتظار دارد. امکان انتقالها و انیمیشنهای روان رنگ را فراهم میکند.<image>: یک مقدار تصویر (مانندurl(image.jpg),linear-gradient(...)) انتظار دارد.<integer>: یک مقدار صحیح (مانند1,-10,0) انتظار دارد.<angle>: یک مقدار زاویه (مانند45deg,0.5rad,200grad) انتظار دارد. برای انیمیشن کردن چرخشها مفید است.<time>: یک مقدار زمان (مانند1s,500ms) انتظار دارد. برای کنترل مدت زمان یا تأخیر انیمیشن از طریق پراپرتیهای سفارشی مفید است.<resolution>: یک مقدار رزولوشن (مانند300dpi,96dpi) انتظار دارد.<transform-list>: لیستی از توابع transform (مانندtranslateX(10px) rotate(45deg)) انتظار دارد. امکان انیمیشن کردن تبدیلات پیچیده را فراهم میکند.<custom-ident>: یک شناسه سفارشی (یک رشته) انتظار دارد. شبیه به یکenumاست.<string>: یک مقدار رشتهای (مانند"Hello World") انتظار دارد. مراقب این مورد باشید، زیرا انیمیشن کردن رشتهها به طور کلی پشتیبانی نمیشود.- سینتکسهای سفارشی: شما میتوانید با استفاده از ترکیب موارد بالا و عملگرهای
|(یا)، `[]` (گروهبندی)، `+` (یک یا بیشتر)، `*` (صفر یا بیشتر)، و `?` (صفر یا یک) سینتکسهای پیچیدهتری ایجاد کنید. به عنوان مثال:<length> | <percentage>به یک مقدار طول یا درصد اجازه میدهد.
انتخاب syntax صحیح برای بهرهبرداری از قدرت کامل @property ضروری است.
مثالهای عملی از @property
بیایید به چند مثال عملی از نحوه استفاده از @property در CSS خود نگاهی بیندازیم.
مثال ۱: انیمیشن رنگ پسزمینه
فرض کنید میخواهید رنگ پسزمینه یک دکمه را انیمیت کنید. میتوانید از @property برای ثبت یک پراپرتی سفارشی برای رنگ پسزمینه استفاده کنید و سپس آن را با استفاده از transitionهای CSS انیمیت کنید.
@property --bg-color {
syntax: '<color>';
inherits: false;
initial-value: #fff;
}
.button {
background-color: var(--bg-color);
transition: --bg-color 0.3s ease;
}
.button:hover {
--bg-color: #f00; /* قرمز */
}
در این مثال، ما پراپرتی سفارشی --bg-color را با سینتکس <color> ثبت میکنیم، به این معنی که انتظار یک مقدار رنگ را دارد. initial-value روی سفید (#fff) تنظیم شده است. وقتی ماوس روی دکمه قرار میگیرد، --bg-color به قرمز (#f00) تغییر میکند و transition به آرامی تغییر رنگ پسزمینه را انیمیت میکند.
مثال ۲: کنترل شعاع مرز با یک عدد
میتوانید از @property برای کنترل شعاع مرز (border radius) یک عنصر و انیمیشن آن استفاده کنید.
@property --border-radius {
syntax: '<length>';
inherits: false;
initial-value: 0px;
}
.rounded-box {
border-radius: var(--border-radius);
transition: --border-radius 0.5s ease;
}
.rounded-box:hover {
--border-radius: 20px;
}
در اینجا، ما --border-radius را به عنوان یک <length> ثبت میکنیم، و اطمینان حاصل میکنیم که مقادیر طول مانند px، em یا % را میپذیرد. مقدار اولیه 0px است. هنگام قرار گرفتن ماوس روی .rounded-box، شعاع مرز به 20px انیمیت میشود.
مثال ۳: انیمیشن کردن آفست سایه
فرض کنید میخواهید آفست افقی یک سایه باکس (box shadow) را انیمیت کنید.
@property --shadow-offset-x {
syntax: '<length>';
inherits: false;
initial-value: 0px;
}
.shadowed-box {
box-shadow: var(--shadow-offset-x) 5px 10px rgba(0, 0, 0, 0.5);
transition: --shadow-offset-x 0.3s ease;
}
.shadowed-box:hover {
--shadow-offset-x: 10px;
}
در این مورد، --shadow-offset-x به عنوان یک <length> ثبت شده و مقدار اولیه آن 0px است. پراپرتی box-shadow از این پراپرتی سفارشی برای آفست افقی خود استفاده میکند. هنگام هاور، آفست به 10px انیمیت میشود.
مثال ۴: استفاده از <custom-ident> برای تمبندی (Theming)
سینتکس <custom-ident> به شما اجازه میدهد مجموعهای از مقادیر رشتهای از پیش تعریف شده را تعریف کنید، و به طور موثر یک enum برای متغیرهای CSS خود ایجاد کنید. این برای تمبندی یا کنترل حالتهای متمایز مفید است.
@property --theme {
syntax: '<custom-ident>';
inherits: true;
initial-value: light;
}
:root {
--theme: light; /* تم پیشفرض */
}
body {
background-color: var(--theme) == light ? #fff : #333;
color: var(--theme) == light ? #000 : #fff;
}
.dark-theme {
--theme: dark;
}
در اینجا، --theme با سینتکس <custom-ident> ثبت شده است. اگرچه ما به صراحت شناسههای مجاز را در خود قانون @property لیست نمیکنیم، اما کد نشان میدهد که آنها `light` و `dark` هستند. سپس CSS از منطق شرطی (var(--theme) == light ? ... : ...) برای اعمال استایلهای مختلف بر اساس تم فعلی استفاده میکند. افزودن کلاس `dark-theme` به یک عنصر، تم را به تاریک تغییر میدهد. توجه داشته باشید که منطق شرطی با استفاده از `var()` یک استاندارد CSS نیست و اغلب به پیشپردازندهها یا جاوااسکریپت نیاز دارد. یک رویکرد استانداردتر از کلاسهای CSS و وراثت استفاده میکند:
@property --theme {
syntax: '<custom-ident>';
inherits: true;
initial-value: light;
}
:root {
--theme: light;
}
body {
background-color: #fff;
color: #000;
}
body[data-theme="dark"] {
background-color: #333;
color: #fff;
}
/* جاوااسکریپت برای تغییر تم */
/* document.body.setAttribute('data-theme', 'dark'); */
در این مثال بازبینی شده، ما از یک اتریبیوت data-theme روی عنصر body برای کنترل تم استفاده میکنیم. جاوااسکریپت (که کامنت شده است) برای تغییر این اتریبیوت بین `light` و `dark` استفاده میشود. این یک رویکرد قویتر و استانداردتر برای تمبندی با متغیرهای CSS است.
مزایای استفاده از @property
استفاده از @property چندین مزیت دارد:
- بهبود خوانایی و قابلیت نگهداری کد: با تعریف صریح نوع مقدار مورد انتظار برای یک پراپرتی سفارشی، کد خود را قابل فهمتر و کمتر مستعد خطا میکنید.
- قابلیتهای انیمیشن پیشرفته:
@propertyامکان انتقالها و انیمیشنهای روان را برای پراپرتیهای سفارشی فراهم میکند و امکانات جدیدی برای ایجاد رابطهای کاربری پویا و جذاب باز میکند. - عملکرد بهتر: مرورگرها میتوانند رندر کردن عناصر با استفاده از پراپرتیهای سفارشی ثبت شده را بهینه کنند که منجر به بهبود عملکرد میشود.
- ایمنی نوع (Type Safety): مرورگر بررسی میکند که مقدار اختصاص داده شده با سینتکس اعلام شده مطابقت دارد، که از رفتار غیرمنتظره جلوگیری میکند و دیباگ کردن را آسانتر میکند. این امر به ویژه در پروژههای بزرگ که توسعهدهندگان زیادی در کدبیس مشارکت دارند مفید است.
- مقادیر پیشفرض: اطمینان از اینکه یک پراپرتی سفارشی همیشه یک مقدار معتبر دارد، حتی اگر به صراحت تنظیم نشده باشد، از خطاها جلوگیری کرده و استحکام CSS شما را بهبود میبخشد.
سازگاری مرورگر
تا اواخر سال ۲۰۲۳، @property پشتیبانی خوب اما نه جهانی در مرورگرها دارد. در اکثر مرورگرهای مدرن از جمله Chrome، Firefox، Safari و Edge پشتیبانی میشود. با این حال، مرورگرهای قدیمیتر ممکن است از آن پشتیبانی نکنند. همیشه قبل از استفاده از @property در محیط پروداکشن، آخرین اطلاعات سازگاری مرورگر را در وبسایتهایی مانند Can I use... بررسی کنید.
برای مدیریت مرورگرهای قدیمیتر، میتوانید از کوئریهای ویژگی (@supports) برای ارائه استایلهای جایگزین استفاده کنید:
@supports (--property: value) {
/* استایلهایی که از @property استفاده میکنند */
}
@supports not (--property: value) {
/* استایلهای جایگزین برای مرورگرهایی که از @property پشتیبانی نمیکنند */
}
--property و value را با یک پراپرتی سفارشی واقعی و مقدار آن جایگزین کنید.
چه زمانی از @property استفاده کنیم
استفاده از @property را در سناریوهای زیر در نظر بگیرید:
- هنگامی که نیاز به انیمیشن کردن پراپرتیهای سفارشی دارید: این اصلیترین مورد استفاده برای
@propertyاست. ثبت پراپرتی با سینتکس صحیح، انیمیشنهای روان را ممکن میسازد. - هنگامی که میخواهید ایمنی نوع را برای پراپرتیهای سفارشی اعمال کنید: اگر میخواهید اطمینان حاصل کنید که یک پراپرتی سفارشی همیشه مقداری از یک نوع خاص را در خود نگه میدارد، از
@propertyبرای ثبت آن استفاده کنید. - هنگامی که میخواهید یک مقدار پیشفرض برای یک پراپرتی سفارشی ارائه دهید: توصیفگر
initial-valueبه شما امکان میدهد یک مقدار جایگزین مشخص کنید. - در پروژههای بزرگ:
@propertyقابلیت نگهداری کد را افزایش داده و از خطاها جلوگیری میکند، که آن را به ویژه برای پروژههای بزرگ با توسعهدهندگان متعدد مفید میسازد. - هنگام ایجاد کامپوننتهای قابل استفاده مجدد یا سیستمهای طراحی:
@propertyمیتواند به تضمین ثبات و پیشبینیپذیری در سراسر کامپوننتهای شما کمک کند.
اشتباهات رایج برای اجتناب
- فراموش کردن توصیفگر
syntax: بدون توصیفگرsyntax، مرورگر نوع مقدار مورد انتظار را نخواهد دانست و انیمیشنها به درستی کار نخواهند کرد. - استفاده از مقدار
syntaxاشتباه: انتخاب سینتکس اشتباه میتواند منجر به رفتار غیرمنتظره شود. اطمینان حاصل کنید که سینتکسی را انتخاب میکنید که به درستی نوع مقدار مورد انتظار را منعکس میکند. - ارائه نکردن
initial-value: بدون یک مقدار اولیه، پراپرتی سفارشی ممکن است تعریف نشده باشد و منجر به خطا شود. همیشه یک مقدار پیشفرض معقول ارائه دهید. - استفاده بیش از حد از
*به عنوان سینتکس: اگرچه راحت است، استفاده از*مزایای بررسی نوع و انیمیشن را از بین میبرد. فقط زمانی از آن استفاده کنید که واقعاً نیاز به اجازه دادن به هر نوع مقداری دارید. - نادیده گرفتن سازگاری مرورگر: همیشه سازگاری مرورگر را بررسی کرده و استایلهای جایگزین برای مرورگرهای قدیمیتر ارائه دهید.
@property و CSS Houdini
@property بخشی از مجموعه بزرگتری از APIها به نام CSS Houdini است. Houdini به توسعهدهندگان اجازه میدهد تا به موتور رندر مرورگر دسترسی پیدا کنند و کنترل بیسابقهای بر فرآیند استایلدهی و طرحبندی داشته باشند. سایر APIهای Houdini عبارتند از:
- Paint API: به شما امکان میدهد تصاویر پسزمینه و مرزهای سفارشی تعریف کنید.
- Animation Worklet API: راهی برای ایجاد انیمیشنهای با کارایی بالا فراهم میکند که مستقیماً در نخ کامپوزیتور مرورگر اجرا میشوند.
- Layout API: شما را قادر میسازد الگوریتمهای طرحبندی سفارشی تعریف کنید.
- Parser API: دسترسی به پارسر CSS مرورگر را فراهم میکند.
@property یک API نسبتاً ساده از Houdini برای یادگیری است، اما دری را برای کاوش در ویژگیهای پیشرفتهتر Houdini باز میکند.
نتیجهگیری
@property یک at-rule قدرتمند در CSS است که قابلیتهای پیشرفتهای را برای پراپرتیهای سفارشی باز میکند. با ثبت پراپرتیهای سفارشی در مرورگر، میتوانید ایمنی نوع را اعمال کنید، انیمیشنهای روان را فعال کنید و استحکام کلی کد CSS خود را بهبود بخشید. اگرچه پشتیبانی مرورگرها جهانی نیست، اما مزایای استفاده از @property، به ویژه در پروژههای بزرگ و سیستمهای طراحی، آن را به ابزاری ارزشمند برای توسعه وب مدرن تبدیل میکند. @property را بپذیرید و مهارتهای CSS خود را به سطح بالاتری ببرید!