EduFlow
إتقان CSS الحديثة
⁦0%⁩

الوحدة 1 · الـ Cascade كما هو فعلًا

الـ Custom Properties و@property

18 دقراءة 4 دبيئة تجريب الكود

الدرس في لمحة

استخدم الـ custom properties كواجهة عامة للـ component، وافهم متى يفشل الاستبدال في var()، وسجّل خصائص ذات نوع محدّد بـ @property لتُفحص صحّتها وتتحرّك بسلاسة.

  1. 1component بمقبض واحد
  2. 2حين يسوء الاستبدال
  3. 3سجّل الخاصية بـ @property
  4. 4تحريك ما كان يقفز
  5. 5دورك الآن

لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.

تأتي بطاقات الجلسات في Waypoint في أربعة مسارات (Design وPerformance وAccessibility وPlatform)، ولكل مسار لونه الخاص للحدّ الجانبي والشارة وحالة المرور فوق العنوان. النسخة الأولى كانت فيها قاعدة لكل مسار لكل عنصر: اثنتا عشرة قاعدة، وثالثة عشرة تُضاف كلما أضاف فريق التسويق مسارًا.

الـ custom properties (الخصائص المخصّصة، أو «متغيّرات CSS») تحوّل ذلك إلى قاعدة واحدة لكل مسار، وبطاقة تقرأ لونها من مقبض واحد.

component بمقبض واحد

session-card.css
.session-card {
  border-inline-start: 6px solid var(--track-color, #64748b);
}
.session-card .badge {
  background: var(--track-color, #64748b);
  color: white;
}

.track-design { --track-color: #db2777; }
.track-perf   { --track-color: #0891b2; }
HTML
<article class="session-card track-design">…</article>

أمران يجعلان هذا يعمل. الأول أن الـ custom properties موروثة: ضبط --track-color على البطاقة يجعلها مرئية للشارة داخلها. والثاني أن var() تُحسم عند العنصر الذي يستخدمها، في وقت حساب القيمة، فتستبدل كل بطاقة قيمتها الخاصة. والوسيط الثاني في var() هو القيمة البديلة، ولا تُستخدم إلا حين لا تكون الخاصية مضبوطة إطلاقًا.

المكان الذي تضبط فيه الـ custom property مهم. الـ design tokens العامة (ألوان العلامة التجارية وسلّم المسافات ومجموعات الخطوط) مكانها :root، ليرثها كل عنصر. أما tokens الـ component مثل --track-color فمكانها الـ component نفسه، لتبقى محلية وتستطيع بطاقة أن تختلف عن جارتها. وتغيير خاصية على :root من JavaScript يجبر المتصفّح على إعادة حساب الأنماط للشجرة كلها التي تستخدمها، لذا فإن ما يتغيّر كثيرًا، مثل موضع المؤشّر، اضبطه على أصغر عنصر يحتاج إليه.

فكّر في --track-color على أنها الواجهة العامة (API) للبطاقة. أيّ شخص يستطيع تغيير ثيم البطاقة من الخارج، في قالب CMS أو صفحة حملة لمرة واحدة، دون أن يعرف تفاصيلها الداخلية.

حين يسوء الاستبدال

الـ custom properties غير المسجّلة مجرد سلاسل من الرموز. المتصفّح لا يعرف أن --track-color يُفترض أن تكون لونًا، لذا فإن --track-color: 12px تصريح صالح تمامًا. المشكلة تظهر لاحقًا، حين تُسقط var() القيمة 12px في لون border-inline-start.

وهكذا أطلقت Waypoint بطاقة بلا حدّ للمسار إطلاقًا وبشارة شفّافة: كتب الـ CMS القيمة 12px في حقل اللون، ولم يعترض شيء.

سجّل الخاصية بـ @property

تخبر @property المتصفّح بماهية الـ custom property:

CSS
@property --track-color {
  syntax: "<color>";
  inherits: true;
  initial-value: #64748b;
}

الآن تتغيّر ثلاثة أشياء:

  1. فحص الصحة. القيمة التي ليست <color> تجعل الخاصية تسقط إلى بديل آمن: تتصرّف كأنها غير مضبوطة، فتأخذ الخاصية الموروثة قيمة العنصر الأب، وتنتهي السلسلة عند initial-value إن لم يضبطها أحد. فتحصل البطاقة المعطوبة على حدّ رمادي مائل إلى الزرقة بدل ألّا يكون لها حدّ.
  2. القيم المحسوبة لها نوع. getComputedStyle(card).getPropertyValue('--track-color') تُرجع rgb(219, 39, 119)، لا النص الخام الذي كتبته.
  3. الانتقال التدريجي. المتصفّح يعرف كيف يمزج بين لونين، فيمكن للخاصية أن تدخل في transition.

يقبل الواصف syntax أنواعًا مثل <color> و<length> و<length-percentage> و<number> و<percentage> و<angle> و<time> و<integer>، إضافةً إلى "*" لأيّ شيء. وinitial-value مطلوبة ما لم تكن الصيغة "*"، ويجب أن تكون مستقلة حسابيًا: 10px مقبولة، أما 2em فلا.

تحريك ما كان يقفز

هذا تأثير مرور لا يمكن تحقيقه إلا بالتسجيل. الحافة العلوية للبطاقة تدرّج لوني زاويته custom property:

CSS
@property --sheen-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 90deg;
}

.session-card {
  background: linear-gradient(var(--sheen-angle), #f5f3ff, white 60%);
  transition: --sheen-angle 400ms ease;
}
.session-card:hover {
  --sheen-angle: 160deg;
}

دون @property لا يستطيع المتصفّح الانتقال تدريجيًا بين سلاسل رموز، فيقفز التدرّج من زاوية إلى أخرى. ومعها تتحرّك الزاوية بسلاسة. وinherits: false هي الصواب هنا: الزاوية تخصّ خلفية هذه البطاقة، ولا ينبغي أن تصل إلى العناصر الأبناء.

دورك الآن

يعيد التمرين إنتاج خطأ الـ CMS: قيمة --track-color في إحدى البطاقات هي 12px. سجّل الخاصية لتسقط القيم الخاطئة إلى الرمادي المائل إلى الزرقة (slate)، وتأكّد من أن ألوان المسارات الحقيقية ما زالت تظهر. ويواصل الدرس التالي العمل على هذه البطاقات بالـ nesting الأصلي و:has()، الذي يتيح للبطاقة أن تتفاعل مع ما بداخلها.

أهم النقاط

  • الـ custom properties موروثة افتراضيًا وتُستبدل حيث تُستخدم var()، لذا فإن ضبط واحدة منها على العنصر الأب يغيّر ثيم كل عنصر داخله يقرؤها.
  • إذا أنتجت var() قيمة غير صالحة تصبح الخاصية غير صالحة في وقت حساب القيمة؛ فيستخدم المتصفّح القيمة الموروثة أو الابتدائية، لا تصريحك السابق.
  • الـ custom property غير المسجّلة سلسلة من الرموز بلا نوع، لذا لا يستطيع المتصفّح فحص صحّتها ولا الانتقال بين قيمها تدريجيًا في transition.
  • @property تعطي الـ custom property صيغةً وقيمةً ابتدائية وعلامةً للوراثة، فتسقط القيم الخاطئة إلى بديل آمن، وتصبح الخاصية قابلة للتحريك.

قراءات إضافية

تحقّق من فهمك

4 أسئلة

السؤال 1 من 4

ما الـ padding الذي يأخذه .card؟

CSS
.card {
  --space: blue;
  padding: 24px;
  padding: var(--space);
}
السؤال 2 من 4

سجّلت @property --angle { syntax: '<angle>'; inherits: false; initial-value: 0deg; }. ما الذي يعطيك إيّاه هذا ولا تعطيه --angle غير المسجّلة؟

السؤال 3 من 4

أين يجب ضبط لون التمييز في بطاقة جلسة بحيث تستخدم بطاقة .track-design وكل ما بداخلها اللون الوردي؟

السؤال 4 من 4

خاصية مسجّلة لها syntax: '<color>'; inherits: true; initial-value: gray، وبطاقة تضبط --accent: 12px، والعنصر الأب لا يضبط --accent. ما القيمة التي تنتهي إليها البطاقة؟

تدريب

بيئة تجريب الكود

سجّل لون المسار

كتب الـ CMS القيمة 12px في --track-color الخاصة ببطاقة Lightning Talks، ففقد حدّها وشارتها لونهما. سجّل --track-color بـ @property على أنها <color> موروثة وقيمتها الابتدائية #64748b (رمادي مائل إلى الزرقة). يجب أن تحتفظ بطاقتا Design (#db2777) وPerformance (#0891b2) بلونيهما، وأن تسقط البطاقة المعطوبة إلى الرمادي المائل إلى الزرقة.

<section class="schedule">
  <article class="session-card track-design" id="s1">
    <h2>Designing in oklch()</h2>
    <span class="badge">Design</span>
  </article>
  <article class="session-card track-perf" id="s2">
    <h2>The Cost of a Frame</h2>
    <span class="badge">Performance</span>
  </article>
  <article class="session-card track-cms" id="s3">
    <h2>Lightning Talks</h2>
    <span class="badge">Misc</span>
  </article>
</section>جارٍ تحميل المحرّر…

Ctrl/⌘ + Enter للتشغيل · يعمل في بيئة معزولة داخل متصفّحك. لا شيء يغادر جهازك.

المعاينة

الـ console

(لا مخرجات)

الفحوص

  • بطاقة Design وردية
  • بطاقة Performance سماوية (cyan)
  • البطاقة ذات القيمة الخاطئة تسقط إلى الرمادي المائل إلى الزرقة
  • –track-color مسجّلة على أنها لون