خصائص CSS المخصصة في The Cascade
نشرت: 2022-03-10في الشهر الماضي ، أجريت محادثة على Twitter حول الفرق بين الأنماط "المحددة النطاق" (التي تم إنشاؤها في عملية الإنشاء) والأنماط "المتداخلة" الأصلية في CSS. سألت لماذا يتجنب المطورون ، حسب الروايات المتناقلة ، خصوصية محددات الهوية ، بينما يتبنون "الأنماط المحددة النطاق" التي تم إنشاؤها بواسطة JavaScript؟ اقترح كيث غرانت أن الاختلاف يكمن في موازنة التسلسل * والميراث ، أي إعطاء الأفضلية للقرب على الخصوصية. لنلقي نظرة.
الشلال
يعتمد تسلسل CSS على ثلاثة عوامل:
- يتم تحديد الأهمية من خلال العلامة
!important
وأصل النمط (المستخدم> المؤلف> المتصفح) - خصوصية المحددات المستخدمة (مضمنة> معرف> فئة> عنصر)
- ترتيب المصدر للشفرة نفسها (الأحدث لها الأسبقية)
لم يتم ذكر القرب في أي مكان - علاقة شجرة DOM بين أجزاء المحدد. ستكون كلتا الفقرتين أدناه باللون الأحمر ، على الرغم من أن #inner p
يصف علاقة أوثق من #outer p
للفقرة الثانية:
<section> <p>This text is red</p> <div> <p>This text is also red!</p> </div> </section>
#inner p { color: green; } #outer p { color: red; }
كلا المحددين لهما نفس الخصوصية ، كلاهما يصف نفس العنصر p
، ولا يتم وضع علامة على أي منهما على أنه !important
- لذا فإن النتيجة تستند إلى ترتيب المصدر وحده.
أنماط BEM والنطاق
تُستخدم اصطلاحات التسمية مثل BEM ("Block__Element- المُعدِّل") لضمان "تحديد نطاق" كل فقرة لأحد الوالدين فقط ، مع تجنب التتالي تمامًا. يتم إعطاء "عناصر" الفقرة فئات فريدة خاصة بسياق "الكتلة" الخاص بها:
<section class="outer"> <p class="outer__p">This text is red</p> <div class="inner"> <p class="inner__p">This text is green!</p> </div> </section>
.inner__p { color: green; } .outer__p { color: red; }
لا تزال هذه المحددات لها نفس الأهمية النسبية ، والخصوصية ، وترتيب المصدر - لكن النتائج مختلفة. تعمل أدوات CSS "ذات النطاق" أو "المعياري" على أتمتة هذه العملية ، وإعادة كتابة CSS لنا ، بناءً على HTML. في الكود أدناه ، يتم تحديد نطاق كل فقرة لأصلها المباشر:
<section outer-scope> <p outer-scope>This text is red</p> <div outer-scope inner-scope> <p inner-scope>This text is green!</p> </div> </section>
p[inner-scope] { color: green } p[outer-scope] { color: red; }
ميراث
القرب ليس جزءًا من السلسلة ، ولكنه جزء من CSS. هذا هو المكان الذي تصبح فيه الوراثة مهمة. إذا أسقطنا p
من محدداتنا ، فسترث كل فقرة لونًا من أقرب سلف لها:
#inner { color: green; } #outer { color: red; }
نظرًا لأن #inner
و #outer
يصفان عناصر مختلفة ، فإن div
section
الخاص بنا على التوالي ، يتم تطبيق كلا خاصيتي اللون دون تعارض. لم يتم تحديد لون العنصر p
المتداخل ، لذلك يتم تحديد النتائج بالوراثة (لون الأصل المباشر) بدلاً من التتالي . يكون للتقارب الأسبقية ، وتتجاوز قيمة #inner
# جهاز #outer
.
ولكن هناك مشكلة: من أجل استخدام الوراثة ، نقوم بتصميم كل شيء داخل section
و div
. نريد استهداف لون الفقرة على وجه التحديد.
(إعادة) تقديم الخصائص المخصصة
توفر الخصائص المخصصة حلاً جديدًا متوافقًا مع المستعرض ؛ يرثون مثل أي خاصية أخرى ، لكن لا يتعين استخدامهم حيث يتم تعريفهم . باستخدام CSS العادي ، بدون أي اصطلاحات تسمية أو أدوات بناء ، يمكننا إنشاء نمط مستهدف وسياقي ، مع إعطاء الأولوية للتقارب على التسلسل:
p { color: var(--paragraph); } #inner { --paragraph: green; } #outer { --paragraph: red; }
ترث خاصية --paragraph
تمامًا مثل خاصية color
(اللون) ، لكننا الآن نتحكم في كيفية ومكان تطبيق هذه القيمة بالضبط. تعمل خاصية --paragraph
بشكل مشابه للمعامل الذي يمكن تمريره إلى المكون p
، إما من خلال التحديد المباشر (قواعد الخصوصية) أو السياق (قواعد التقارب).
أعتقد أن هذا يكشف عن إمكانية وجود خصائص مخصصة نربطها غالبًا بالوظائف أو الخلطات أو المكونات.
"وظائف" ومعلمات مخصصة
تستند جميع الوظائف والمزج والمكونات على نفس الفكرة: رمز قابل لإعادة الاستخدام ، يمكن تشغيله باستخدام معلمات إدخال مختلفة للحصول على نتائج متسقة ولكن قابلة للتكوين. يكمن الاختلاف في ما يفعلونه بالنتائج. سنبدأ بمتغير خطي التدرج ، وبعد ذلك يمكننا توسيعه إلى أشكال أخرى:
html { --stripes: linear-gradient( to right, powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); }
يتم تحديد هذا المتغير على عنصر html
الجذر (يمكن أيضًا استخدام :root
، لكن هذا يضيف خصوصية غير ضرورية) ، لذلك سيكون المتغير الشريطي متاحًا في كل مكان في المستند. يمكننا تطبيقه في أي مكان يدعم التدرجات:
body { background-image: var(--stripes); }
مضيفا المعلمات
تُستخدم الدوال مثل المتغيرات ، لكنها تحدد معلمات لتغيير المخرجات. يمكننا تحديث متغير --stripes
بنا ليكون أكثر شبهاً بالوظيفة عن طريق تحديد بعض المتغيرات الشبيهة بالمعامل داخله. سأبدأ بالاستبدال to right
بـ var(--stripes-angle)
، لإنشاء معلمة لتغيير الزاوية:
html { --stripes: linear-gradient( var(--stripes-angle), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); }
هناك معلمات أخرى يمكننا إنشاؤها ، اعتمادًا على الغرض الذي من المفترض أن تخدمه الوظيفة. هل يجب أن نسمح للمستخدمين باختيار ألوان الشريط الخاصة بهم؟ إذا كان الأمر كذلك ، فهل تقبل وظيفتنا 5 معلمات مختلفة للألوان أو 3 فقط ستخرج إلى الداخل كما لدينا الآن؟ هل نريد إنشاء معلمات للتوقفات اللونية أيضًا؟ كل معلمة نضيفها توفر المزيد من التخصيص على حساب البساطة والاتساق.
لا توجد إجابة صحيحة عالمية لهذا التوازن - بعض الوظائف تحتاج إلى أن تكون أكثر مرونة ، والبعض الآخر يحتاج إلى أن يكون أكثر رأيا. توجد التجريدات لتوفير الاتساق وسهولة القراءة في التعليمات البرمجية الخاصة بك ، لذا خذ خطوة للوراء واسأل عن أهدافك. ما الذي يحتاج حقًا إلى أن يكون قابلاً للتخصيص ، وأين يجب تطبيق الاتساق؟ في بعض الحالات ، قد يكون من المفيد أكثر أن يكون لديك وظيفتان عنيدتين ، بدلاً من وظيفة واحدة قابلة للتخصيص بالكامل.
لاستخدام الوظيفة أعلاه ، نحتاج إلى تمرير قيمة --stripes-angle
، وتطبيق الإخراج على خاصية إخراج CSS ، مثل background-image
:
/* in addition to the code above… */ html { --stripes-angle: 75deg; background-image: var(--stripes); }
موروث مقابل يونيفرسال
لقد حددت دالة --stripes
على عنصر html
بدافع العادة. ترث الخصائص المخصصة ، وأريد أن تكون وظيفتي متاحة في كل مكان ، لذلك من المنطقي وضعها على عنصر الجذر. يعمل هذا جيدًا لوراثة متغيرات مثل --brand-color: blue
، لذلك قد نتوقع أيضًا أن تعمل مع "وظيفتنا" أيضًا. ولكن إذا حاولنا استخدام هذه الوظيفة مرة أخرى على محدد متداخل ، فلن تعمل:
div { --stripes-angle: 90deg; background-image: var(--stripes); }
يتم تجاهل --stripes-angle
الجديدة تمامًا. اتضح أننا لا نستطيع الاعتماد على الوراثة للوظائف التي تحتاج إلى إعادة حساب. هذا لأنه يتم حساب كل قيمة خاصية مرة واحدة لكل عنصر (في حالتنا ، عنصر جذر html
) ، ثم يتم توارث القيمة المحسوبة . من خلال تحديد وظيفتنا في جذر المستند ، لا نجعل الوظيفة بالكامل متاحة للأحفاد - فقط النتيجة المحسوبة لوظيفتنا.
يكون هذا منطقيًا إذا قمت --stripes-angle
المتتالية. مثل أي خاصية CSS موروثة ، فهي متاحة للأحفاد وليس للأسلاف. القيمة التي قمنا بتعيينها على div
متداخلة غير متاحة للدالة التي حددناها في أصل جذر html
. من أجل إنشاء وظيفة متاحة عالميًا والتي ستعيد حساب أي عنصر ، يتعين علينا تحديدها في كل عنصر:
* { --stripes: linear-gradient( var(--stripes-angle), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); }
يجعل المحدد العام وظيفتنا متاحة في كل مكان ، ولكن يمكننا تحديدها بشكل أضيق إذا أردنا ذلك. الشيء المهم هو أنه لا يمكنه إعادة الحساب إلا إذا تم تعريفه صراحةً. وهنا بعض البدائل:
/* make the function available to elements with a given selector */ .stripes { --stripes: /* etc… */; } /* make the function available to elements nested inside a given selector */ .stripes * { --stripes: /* etc… */; } /* make the function available to siblings following a given selector */ .stripes ~ * { --stripes: /* etc… */; }
يمكن تمديد هذا بأي منطق محدد لا يعتمد على الوراثة.
المعلمات المجانية والقيم الاحتياطية
في المثال أعلاه ، var(--stripes-angle)
ليس له قيمة ولا احتياطي. على عكس متغيرات Sass أو JS التي يجب تعريفها أو إنشاء مثيل لها قبل استدعائها ، يمكن استدعاء خصائص CSS المخصصة دون أن يتم تعريفها على الإطلاق. يؤدي هذا إلى إنشاء متغير "مجاني" ، مشابه لمعامل دالة يمكن توريثه من السياق.
يمكننا في النهاية تحديد المتغير في html
أو :root
(أو أي سلف آخر) لتعيين قيمة موروثة ، ولكن علينا أولاً أن نأخذ في الاعتبار الرجوع إذا لم يتم تحديد قيمة. هناك العديد من الخيارات ، اعتمادًا على السلوك الذي نريده بالضبط
- بالنسبة للمعلمات "المطلوبة" ، لا نريد رجوعًا. كما هي ، لن تفعل الوظيفة شيئًا حتى يتم تحديد
--stripes-angle
. - بالنسبة للمعلمات "الاختيارية" ، يمكننا توفير قيمة احتياطية في دالة
var()
. بعد اسم المتغير نضيف فاصلة متبوعة بالقيمة الافتراضية:
var(--stripes-angle, 90deg)
يمكن أن يكون لكل دالة var()
عنصر احتياطي واحد فقط - لذا فإن أي فواصل إضافية ستكون جزءًا من تلك القيمة. هذا يجعل من الممكن توفير الافتراضات المعقدة بفاصلات داخلية:
html { /* Computed: Hevetica, Ariel, sans-serif */ font-family: var(--sans-family, Hevetica, Ariel, sans-serif); /* Computed: 0 -1px 0 white, 0 1px 0 black */ test-shadow: var(--shadow, 0 -1px 0 white, 0 1px 0 black); }
يمكننا أيضًا استخدام المتغيرات المتداخلة لإنشاء قواعد التسلسل الخاصة بنا ، مع إعطاء أولويات مختلفة للقيم المختلفة:
var(--stripes-angle, var(--global-default-angle, 90deg))
- أولاً ، جرب معاملنا الصريح (
--stripes-angle
) ؛ - الرجوع إلى "افتراضي المستخدم" العام (
--user-default-angle
) إذا كان متاحًا ؛ - أخيرًا ، الرجوع إلى "إعدادات المصنع الافتراضية"
(90deg
).
من خلال تعيين القيم الاحتياطية في var()
بدلاً من تحديد الخاصية المخصصة بشكل صريح ، نضمن عدم وجود قيود محددة أو متتالية على المعلمة. جميع المعلمات *-angle
هي "مجانية" ليتم توريثها من أي سياق.
احتياطات المتصفح مقابل الإجراءات الاحتياطية المتغيرة
عندما نستخدم المتغيرات ، هناك مساران احتياطيان يجب أن نضعهما في الاعتبار:
- ما هي القيمة التي يجب أن تستخدمها المتصفحات التي لا تحتوي على دعم متغير؟
- ما القيمة التي يجب أن تستخدمها المتصفحات التي تدعم المتغيرات ، عندما يكون متغير معين مفقودًا أو غير صالح؟
p { color: blue; color: var(--paragraph); }
بينما ستتجاهل المتصفحات القديمة خاصية إعلان المتغير ، والعودة إلى blue
- ستقرأ المتصفحات الحديثة كليهما وتستخدم الأخير. قد لا يتم تعريف var(--paragraph)
الخاصة بنا ، لكنها صالحة وستتجاوز الخاصية السابقة ، لذا فإن المتصفحات ذات الدعم المتغير ستعود إلى القيمة الموروثة أو الأولية ، كما لو كانت unset
الكلمة الأساسية غير المحددة.
قد يبدو هذا محيرًا في البداية ، ولكن هناك أسباب وجيهة لذلك. الأول تقني: تتعامل محركات المتصفح مع بناء جملة غير صالح أو غير معروف في "وقت التحليل" (الذي يحدث أولاً) ، ولكن لا يتم حل المتغيرات حتى "وقت القيمة المحسوبة" (والذي يحدث لاحقًا).
- في وقت التحليل ، يتم تجاهل التصريحات التي تحتوي على بناء جملة غير صالح تمامًا - التراجع عن الإعلانات السابقة. هذا هو المسار الذي ستتبعه المتصفحات القديمة. تدعم المتصفحات الحديثة بناء الجملة المتغير ، لذلك يتم تجاهل الإعلان السابق بدلاً من ذلك.
- في وقت القيمة المحسوبة ، يتم تصنيف المتغير على أنه غير صالح ، ولكن بعد فوات الأوان - تم تجاهل الإعلان السابق بالفعل. وفقًا للمواصفات ، يتم التعامل مع قيم المتغيرات غير الصالحة بنفس طريقة التعامل مع القيم غير
unset
:
html { color: red; /* ignored as *invalid syntax* by all browsers */ /* - old browsers: red */ /* - new browsers: red */ color: not a valid color; color: var(not a valid variable name); /* ignored as *invalid syntax* by browsers without var support */ /* valid syntax, but invalid *values* in modern browsers */ /* - old browsers: red */ /* - new browsers: unset (black) */ --invalid-value: not a valid color value; color: var(--undefined-variable); color: var(--invalid-value); }
هذا مفيد أيضًا لنا كمؤلفين ، لأنه يسمح لنا باللعب مع المزيد من الإجراءات الاحتياطية المعقدة للمتصفحات التي تدعم المتغيرات ، وتوفر احتياطيًا بسيطًا للمتصفحات القديمة. والأفضل من ذلك ، يسمح لنا ذلك باستخدام الحالة null
/ undefined
لتعيين المعلمات المطلوبة. يصبح هذا مهمًا بشكل خاص إذا أردنا تحويل دالة إلى مزيج أو مكون.
خاصية مخصصة "Mixins"
في Sass ، تُرجع الدوال قيمًا أولية ، بينما تعيد الخلطات عمومًا مخرجات CSS الفعلية مع أزواج قيمة الخاصية. عندما نحدد خاصية --stripes
، دون تطبيقها على أي ناتج مرئي ، فإن النتيجة تشبه الوظيفة. يمكننا أن نجعل ذلك يتصرف مثل مزيج ، من خلال تحديد الناتج عالميًا أيضًا:
* { --stripes: linear-gradient( var(--stripes-angle), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); background-image: var(--stripes); }
طالما --stripes-angle
غير صالحة أو غير محددة ، يفشل التجميع ، ولن يتم تطبيق أي background-image
. إذا حددنا زاوية صالحة لأي عنصر ، فستحسب الدالة وتعطينا الخلفية:
div { --stripes-angle: 30deg; /* generates the background */ }
لسوء الحظ ، سترث قيمة المعلمة هذه ، لذلك يُنشئ التعريف الحالي خلفية عن div
وجميع العناصر الفرعية. لإصلاح ذلك ، علينا أن نتأكد من أن قيمة --stripes-angle
لا ترث ، عن طريق إراحةها على القيمة initial
(أو أي قيمة غير صالحة) على كل عنصر. يمكننا القيام بذلك على نفس المحدد العام:
* { --stripes-angle: initial; --stripes: /* etc… */; background-image: var(--stripes); }
الأنماط المضمنة الآمنة
في بعض الحالات ، نحتاج إلى تعيين المعلمة ديناميكيًا من خارج CSS - بناءً على بيانات من خادم خلفية أو إطار عمل للواجهة الأمامية. باستخدام الخصائص المخصصة ، يمكننا تحديد المتغيرات بأمان في HTML الخاص بنا دون القلق بشأن مشكلات الخصوصية المعتادة:
<div>...</div>
تتميز الأنماط المضمنة بخصوصية عالية ، ومن الصعب جدًا تجاوزها - ولكن مع الخصائص المخصصة ، لدينا خيار آخر: تجاهلها. إذا قمنا بتعيين div إلى background-image: none
(على سبيل المثال) لن يكون لهذا المتغير المضمن أي تأثير. لأخذها أبعد من ذلك ، يمكننا إنشاء متغير وسيط:
* { --stripes-angle: var(--stripes-angle-dynamic, initial); }
الآن لدينا خيار تحديد --stripes-angle-dynamic
في HTML ، أو تجاهلها ، وتعيين --stripes-angle
مباشرة في ورقة الأنماط الخاصة بنا.
قيم محددة مسبقا
للقيم الأكثر تعقيدًا ، أو الأنماط الشائعة التي نريد إعادة استخدامها ، يمكننا أيضًا توفير بعض المتغيرات المحددة مسبقًا للاختيار من بينها:
* { --tilt-down: 6deg; --tilt-up: -6deg; }
واستخدم هذه الإعدادات المسبقة ، بدلاً من تعيين القيمة مباشرةً:
<div>...</div>
يعد هذا أمرًا رائعًا لإنشاء المخططات والرسوم البيانية بناءً على البيانات الديناميكية ، أو حتى تخطيط مخطط اليوم.
المكونات السياقية
يمكننا أيضًا إعادة صياغة "mixin" الخاص بنا كـ "مكون" من خلال تطبيقه على محدد صريح ، وجعل المعلمات اختيارية. بدلاً من الاعتماد على وجود - أو عدم وجود --stripes-angle
لتبديل ناتجنا ، يمكننا الاعتماد على وجود أو عدم وجود محدد مكون. يسمح لنا ذلك بتعيين القيم الاحتياطية بأمان:
[data-stripes] { --stripes: linear-gradient( var(--stripes-angle, to right), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); background-image: var(--stripes); }
من خلال وضع العنصر الاحتياطي داخل دالة var()
، يمكننا ترك --stripes-angle
غير محددة و "free" لترث قيمة من خارج المكون. هذه طريقة رائعة لفضح جوانب معينة من نمط المكون للمدخلات السياقية. حتى الأنماط "المحددة النطاق" التي تم إنشاؤها بواسطة إطار عمل JS (أو التي تم تحديدها داخل Shadow-DOM ، مثل رموز SVG) يمكنها استخدام هذا الأسلوب لكشف معلمات محددة للتأثير الخارجي.
مكونات معزولة
إذا لم نرغب في الكشف عن المعلمة للوراثة ، فيمكننا تحديد المتغير بقيمة افتراضية:
[data-stripes] { --stripes-angle: to right; --stripes: linear-gradient( var(--stripes-angle, to right), powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80% ); background-image: var(--stripes); }
ستعمل هذه المكونات أيضًا مع فئة أو أي محدد صالح آخر ، لكنني اخترت سمة data-
لإنشاء مساحة اسم لأي مُعدِّلات نريدها:
[data-stripes='vertical'] { --stripes-angle: to bottom; } [data-stripes='horizontal'] { --stripes-angle: to right; } [data-stripes='corners'] { --stripes-angle: to bottom right; }
المحددات والمعلمات
غالبًا ما أتمنى أن أتمكن من استخدام سمات البيانات لتعيين متغير - وهي ميزة تدعمها مواصفات CSS3 attr()
، ولكن لم يتم تنفيذها بعد في أي متصفحات (انظر علامة تبويب الموارد للمشكلات المرتبطة في كل متصفح). سيسمح لنا ذلك بربط المحدد بمعامل معين بشكل أوثق:
<div data-stripes="30deg">...</div> /* Part of the CSS3 spec, but not yet supported */ /* attr( , ) */ [data-stripes] { --stripes-angle: attr(data-stripes angle, to right); }
<div data-stripes="30deg">...</div> /* Part of the CSS3 spec, but not yet supported */ /* attr( , ) */ [data-stripes] { --stripes-angle: attr(data-stripes angle, to right); }
<div data-stripes="30deg">...</div> /* Part of the CSS3 spec, but not yet supported */ /* attr( , ) */ [data-stripes] { --stripes-angle: attr(data-stripes angle, to right); }
في غضون ذلك ، يمكننا تحقيق شيء مشابه باستخدام سمة style
:
<div>...</div> /* The `*=` atttribute selector will match a string anywhere in the attribute */ [style*='--stripes-angle'] { /* Only define the function where we want to call it */ --stripes: linear-gradient(…); }
يكون هذا الأسلوب مفيدًا للغاية عندما نريد تضمين خصائص أخرى بالإضافة إلى المعلمة التي يتم تعيينها. على سبيل المثال ، يمكن أن يؤدي تعيين منطقة الشبكة أيضًا إلى إضافة مساحة وخلفية:
[style*='--grid-area'] { background-color: white; grid-area: var(--grid-area, auto / 1 / auto / -1); padding: 1em; }
خاتمة
عندما نبدأ في تجميع كل هذه الأجزاء معًا ، يصبح من الواضح أن الخصائص المخصصة تتجاوز حالات استخدام المتغير الشائعة المألوفة لدينا. نحن لسنا قادرين فقط على تخزين القيم ، ووضعها في نطاق التسلسل - ولكن يمكننا استخدامها لمعالجة التتالي بطرق جديدة ، وإنشاء مكونات أكثر ذكاءً مباشرةً في CSS.
هذا يدعونا لإعادة التفكير في العديد من الأدوات التي اعتمدنا عليها في الماضي - من اصطلاحات التسمية مثل SMACSS و BEM ، إلى الأنماط "المحددة" و CSS-in-JS. تساعد العديد من هذه الأدوات في الالتفاف حول الخصوصية ، أو إدارة الأنماط الديناميكية بلغة أخرى - حالات الاستخدام التي يمكننا الآن معالجتها مباشرةً باستخدام الخصائص المخصصة. يمكن الآن معالجة الأنماط الديناميكية التي احتسبناها غالبًا في JS عن طريق تمرير البيانات الأولية إلى CSS.
في البداية ، قد يُنظر إلى هذه التغييرات على أنها "تعقيد إضافي" - لأننا لسنا معتادين على رؤية المنطق داخل CSS. وكما هو الحال مع جميع التعليمات البرمجية ، يمكن أن تشكل الهندسة الزائدة خطرًا حقيقيًا. لكنني أزعم أنه في كثير من الحالات ، يمكننا استخدام هذه القوة ليس لإضافة التعقيد ، ولكن لنقل التعقيد من أدوات واتفاقيات الطرف الثالث ، والعودة إلى اللغة الأساسية لتصميم الويب ، (والأهم من ذلك) العودة إلى المتصفح. إذا كانت أنماطنا تتطلب حسابًا ، فيجب أن يعيش هذا الحساب داخل CSS الخاص بنا.
كل هذه الأفكار يمكن أن تؤخذ إلى أبعد من ذلك بكثير. بدأت الخصائص المخصصة للتو في رؤية تبني أوسع ، وقد بدأنا للتو في خدش السطح لما هو ممكن. أنا متحمس لرؤية إلى أين يذهب هذا ، وماذا سيأتي الناس أيضًا. استمتع!
قراءة متعمقة
- "حان الوقت لبدء استخدام خصائص CSS المخصصة ،" سيرج Hospodarets
- "دليل إستراتيجي لخصائص CSS المخصصة ،" مايكل ريثمولر