تقنيات كتابة شيفرات CSS احترافية وسهلة الصّيانة


عبد اللطيف ايمش

رأيتُ في الآونة الأخيرة الكثير من الأشخاص يشقون طريقهم بصعوبة في CSS، انطلاقًا من المبتدئين إلى المبرمجين المحترفين؛ بعضهم لا يحب طريقة عمل CSS، ويرون أنَّ استبدال لغة أخرى بلغة CSS هو أمرٌ حسن، وكانت هذه هي نقطة انطلاق مفسرات CSS (مثل Sass و Less)؛ وبعضهم الآخر يستخدم إطارات العمل على أمل أنَّ ذلك سيجعلهم يكتبون شيفرات أقل (ورأينا في درس «ربما لا تحتاج إلى إطار عمل للغة CSS » أنَّ ذلك ليس صحيحًا)؛ بينما تخلى بعض المطورين عن استخدام CSS تمامًا وبدؤوا باستعمال JavaScript بدلًا عنها.
لكنك لا تحتاج دومًا إلى استخدام مُفسِّر CSS في مشاريعك، ولستَ بحاجةٍ إلى استعمال إطار عمل كبير كنقطة بداية لمشروعك، ومن المؤكد أنَّ فكرة استعمال JavaScript لغير غرضها الأصلي هي فكرةٌ سيئة.
سنطالع في هذا الدرس بعض التلميحات والنصائح لكيفية أفضل لكتابة شيفرات CSS سهلة الصيانة، لذا ستصبح ملفات الأنماط أقصر، وفيها قواعد أقل، وستشعر أنَّ CSS أصبحت أداةً مفيدةً واستخدامها مريح بدلًا من أن تفكر في عواقب استعمالها!

css-coding-techniques.png

إنشاء محددات غير مخصصة

تعتمد لغة CSS على التصريح عن «محددات» (selectors) التي تضع فيها القواعد التنسيقية التي تريد تطبيقها على العناصر الموجودة في شجرة DOM. وهنالك بعض القواعد التي لها أولوية على القواعد الأخرى، كتلك التي عُرِّفَت داخل الخاصية style في العنصر نفسه.
على سبيل المثال، إذا كانت لدينا شيفرة HTML و CSS الآتية:

<button class="button-warning">
.button-warning {
  background: red;
}

button, input[type=submit] {
  background: gray;
}

بغض النظر عن أنَّ القاعدة ‎.button-warning قد عرِّفَت قبل قاعدة button, input[type=submit]، لكن لخاصية background فيها أولوية على خاصية background المُعرَّفة في قاعدة button, input[type=submit]. لكن لماذا؟ ما هو المعيار الذي تتبعه لغة CSS لتقرر ما هي القواعد التي لها أولوية على غيرها؟
الجواب هو «التحديد»، فبعض المحددات تُعتبَر أنَّها مخصصة أكثر من غيرها: فمثلًا المُحدِّد ‎#id له أولوية على محدد ‎.class.
ماذا يحدث لو استخدمنا مُحدِّد أكثر تخصيصًا مما يلزم؟ ماذا لو أردنا لاحقًا تجاوز تلك القواعد، سنحتاج حينها إلى مُحدِّد أكثر تخصيصًا. ماذا لو أردنا بعد ذلك أن نتجاوز تلك القيم… نعم سنحتاج إلى مُحدِّد أكثر تخصيصًا، وهكذا حتى تصبح المحددات أطول وأعقد وسينتهي بها المطاف لتمسي صعبة الصيانة والتطوير.
لذا عليك عند كتابة المُحدِّدات أن تسأل نفسك: هل هذا هو أقل مُحدِّد تخصيصًا الذي يعمل عملًا صحيحًا هنا؟
جميع قواعد التحديد مُعرَّفة بشكلٍ رسمي في مواصفة «W3C CSS Selectors»، وستجد في تلك الصفحة جميع التفاصيل المتعلقة بمُحدِّدات CSS. إذا أردتَ مقالةً سهلة الفهم فاطلع على هذه المقالة.

لا تعالج المشاكل بإضافة قواعد جديدة

لنتخيل هذا الموقف الذي يتكرر كثيرًا: هنالك علّة في شيفرة CSS وعرفتَ أنَّ أحد عناصر DOM مُنسَّقٌ تنسيقًا خاطئًا، وأدركتَ أنَّ السبب هو وراثته (inherit) لخاصيةٍ لا يجب أن يرثها.
رجاءً لا تضف شيفرة CSS جديدة لحل المشكلة، فبفعلك لذلك ستصبح الشيفرات عندك كثيرة، وسيصبح تحديد العلل المستقبلية أصعب.
فبدلًا من ذلك، توقف، واستخدام أدوات المطوِّر في متصفحك لتفحص العنصر ومعرفة ما الذي يرثه من خاصيات، ومعرفة ما هي القاعدة التي تُطبَّق على العنصر والتي لا تريدها، ثم تعديل تلك القاعدة لكي لا تؤدي إلى تلك النتيجة.
يمكنك إظهار الأنماط التي يرثها أحد العناصر في متصفح Firefox بالضغط بالزر الأيمن على العنصر ثم اختيار «Inspect element».

1-image00.png

انظر إلى الخاصيات الموروثة، ولاحظ كيف سترى جميع القواعد المُطبَّقة على العنصر، وبالترتيب الذي طُبِّقَت فيه. أي أنَّ القواعد الموجودة في الأعلى هي القواعد الأكثر تحديدًا ولها أولولية على القواعد التي تليها. يمكنك أن ترى وجود خط يمر ببعض الخاصيات، وهذا يعني أنَّ هنالك قاعدة أكثر تخصيصًا أدت إلى تجاوز هذه القاعدة.
يمكنك –إضافةً إلى رؤية القواعد المُطبَّقة على العنصر– أن تُفعِّل أو تلغي تفعيل بعض الخاصيات أو أن تجري تعديلات حية على قيمها ثم تلاحظ النتائج، وهذا مفيدٌ جدًا عند محاولة إصلاح العلل.
قد يتضمن الحل اللازم تطبيقه لإصلاح العلة تعديلًا في إحدى القواعد، أو تغييرًا لقاعدةٍ ما في مكانٍ آخر في صفحة الأنماط؛ وقد يتطلب إصلاح العلة إضافةَ قاعدةٍ جديدةٍ… لكن المهم أن تعلم ما هو الإجراء الصحيح الذي عليك اتخاذه لإصلاح المشكلة.
أقترح عليك أيضًا أن تنظر في إعادة هيكلة الشيفرات (code refactoring)، فصحيحٌ أنَّ CSS ليست لغةً برمجيةً، إلا أنَّها «شيفرات» وعليك أن تأخذ بعين الاعتبار نفس الأمور التي تفعلها مع شيفرات JavaScript أو بايثون: يجب أن تكون الشيفرات مرتبةً وسهلة القراءة ويمكن إعادة هيكلتها عند الحاجة.

لا تستخدم ‎‎!important

هذه النصيحة مضمّنة في القسم السابق، إلا أنني فضَّلتُ ذكرها بمفردها لأهميتها: لا تستخدم ‎!important في شيفرة CSS!
الكلمة المحجوزة ‎!important هي ميزة في CSS تسمح لك بتجاوز الترتيب الافتراضي للأولويات، وهي تستعمل عادةً إن استعجلت إصلاح علّة لكنك لا تملك وقتًا أو ليست عندك رغبة في إصلاحها بمعرفة مسببها الأصلي… من الشائع أيضًا استعمال الكلمة المحجوزة ‎!important عندما تَستخدم إطار عمل CSS ذو قواعد مخصصة جدًا، ومن الصعب تجاوز تلك القيم.
عندما تُضيف ‎!important إلى خاصيةٍ ما، فسيتجاهل المتصفح جميع القواعد التي لها أولوية عليها (أي أنَّ القاعدة «أكثر تخصيصًا»)، وستجد نفسك في ورطة عندما تستعمل ‎!important لتجاوز قاعدة أخرى قد اُستخدمَت فيها ‎!important أيضًا.
الاستعمال المشروع الوحيد للكلمة ‎!important هو عند استخدامك لأدوات التطوير لمحاولة حل مشكلة ما، فعليك في بعض الأحيان أن تعرف ما هي القيم اللازم ضبطها لإصلاح العلة، واستخدام ‎!important في أدوات التطوير وتعديل قواعد CSS تعديلًا حيًا سيسمح لك بمعرفة تلك القيم مع تجاهل القيم الموروثة.
بعد أن تعرف ما هي القيم الصحيحة، فعد إلى الشيفرة وانظر ما هي القواعد التي تتضمن تلك الخاصيات، وعدِّلها كما ينبغي.

لا تجعل px و % هي كل ما تستخدمه من الواحدات

التعامل مع px (البسكلات) و % (النسب المئوية) أصبح بدهيًا، لذا سنشرح بعض الواحدات الأقل شهرةً.

em و rem

من أشهر الواحدات النسبية هي em، حيث يكافئ 1em قياس الخط التابع لذلك العنصر.
لتكن لدينا شيفرة HTML الآتية:

<article>
  <h1>Title</h1>
  <p>One Ring to bring them all and in the darkness bind the.</p>
</article>

وسنستخدم قاعدة CSS وحيدة:

article {
  font-size: 1.25em;
}

تُطبِّق أغلبية المتصفحات قياسًا بمقدار 16 بكسل إلى العنصر الجذر (root element) افتراضيًا (بالمناسبة، يمكن تعديل هذه القيمة من المستخدم، وهذه ميزةٌ رائعةٌ تُسهِّل من قابلية الوصول). أي ستُعرَض نصوص العنصر article بخاصية font-size ذات القيمة 20 بكسل (أي 16 * 1.25).
لكن ماذا عن العنصر h1؟ لفهم ما الذي يحدث تمامًا فسنضيف قاعدة CSS أخرى إلى صفحة الأنماط:

h1 {
  font-size: 1.25em;
}

صحيحٌ أنَّ قيمة الخاصية font-size هي 1.25em أيضًا، أي نفس قياس العنصر article، لكن علينا أن نأخذ بعين الاعتبار أنَّ الخاصية em هي خاصية تجميعية، أي لو كان العنصر h1 ابنًا (child) مباشرًا للعنصر body على سبيل المثال، فستكون قيمة الخاصية font-size هي 20 بكسل (أي 16 * 1.25)؛ لكن عنصر h1 في مثالنا موجودٌ داخل عنصرٍ (العنصر article هنا) له قيمةٌ للخاصية font-size تختلف عن العنصر الجذر، ففي هذه الحالة قياس الخط هو 1.25 مضروبًا بقيمة الخاصية font-size التي يرثها العنصر h1، أي سيكون قياس الخط النهائي للعنصر h1 الموجود داخل العنصر article هو 25 بكسل (أي 16 * 1.25 * 1.25).

2-image01.png

الواحدة em متعددة الاستخدامات وتجعل من السهل تغيير جميع القياسات في الصفحة (حتى لو غيرناها ديناميكيًا)، ولا تُستعمَل فقط على قيمة الخاصية font-size وإنما يمكن توظيفها في الخاصيات الأخرى مثل line-height أو width.

إذا أعجبتكَ فكرة استخدام واحدة قياس نسبةً إلى الحجم الأساسي، لكن لم تحب موضوع تجميع القيم، فيمكنك حينها استخدام rem، واحدة rem شبيهةٌ جدًا بواحدة em إلا أنَّها تتجاهل تجميع القيم، وتأخذ قياس العنصر الجذر فقط.
إذا أخذنا شيفرة CSS للمثال السابق وبدلنا واحدة em إلى rem للعنصر h1:

article { font-size: 1.25em; }
h1 { font-size: 1.25rem; }

ستملك جميع عناصر h1 الخاصية font-size بقيمة 20 بكسل (بافتراض أنَّ قياس العنصر الجذر هو 16px)، بعض النظر إن كان العنصر h1 داخل عنصر article أم لا.

vw و vh

واحدات vm و vh تُمثِّل نسبة من أبعاد «إطار العرض» (viewport)، حيث 1vw هي 1% من عرض «إطار العرض»، بينما 1vh هي 1% من ارتفاع «إطار العرض».
هذه الواحدات مفيدة للغاية، وخصوصًا عندما تريد إنشاء عنصر يأخذ كامل الشاشة (مثل الخلفيات الغامقة للأقسام).

واحدات أخرى

هنالك واحدات أخرى غير شائعة أو مستعملة بكثرة، لكن قد تصادفك في مسيرتك البرمجية، يمكنك تعلم المزيد من المعلومات عنها في هذا الدرس.

استخدم flexbox

تحدثنا عن هذا من قبل في درسٍ سابقٍ عن إطارات عمل CSS «ربما لا تحتاج إلى إطار عمل للغة أضفCSS» ، لكن لا ضير من التذكير أنَّ flexbox سيُبسِّط عملية إنشاء تخطيطات الصفحات أو لمحاذاة العناصر. إذا كان flexbox جديدًا عليك فانظر إلى هذا الدرس التمهيدي.
أجيب بنعم على السؤال البدهي الذي سيخطر ببالك: «هل يمكن استخدام flexbox في الوقت الراهن؟». دعم flexbox في المتصفحات تجاوز نسبة 94%، لذا يمكنك استخدامه حالًا إلا إن كنتَ تريد دعم المتصفحات القديمة. لذا يمكنك التوقف عن كتابة عناصر div الكثيرة ذات الخاصية float والتي يصعب اكتشاف الأخطاء فيها وصيانتها.
راقب أيضًا التطويرات في مجال تنسيق تخطيط الصفحة وخصوصًا Grid ، الذي سيُسهِّل كثيرًا من إنشاء تخطيط الصفحة.

عند استخدام مُفسِّر CSS…

مفسِّرات CSS مثل Sass أو Less مشهورة جدًا في عالم تطوير الواجهات الأمامية لصفحات الويب، وهي أدواتٌ مفيدةٌ جدًا وتسمح لنا (عند استخدامها استخدامًا صحيحًا) أن نعمل بكفاءة كبيرة مع CSS.

لا تسرف في تشعّب المُحدِّدات

إحدى الميزات الشائعة في مُفسِّرات CSS هي تشعّب المحددات (selector nesting)، فمثلًا هذه شيفرة Less:

a {
  text-decoration: none;
  color: blue;

  &.important {
    font-weight: bold;
  }
}

ستُحوَّل إلى قواعد CSS الآتية:

a {
  text-decoration: none;
  color: blue;
}

a.important {
  font-weight: bold;
}

تسمح هذه الميزة لنا بكتابة شيفرات أقل، وتجميع القواعد التي تؤثر على العناصر التي تأتي مع بعضها (عمومًا) في شجرة DOM، وهذه الميزة تساعدك في اكتشاف العلل وإصلاحها.
لكن من الشائع أيضًا الإفراط في استخدام هذه الميزة مما يجعلك تعيد كتابة شجرة DOM بكاملها في محددات CSS، لذا إذا كانت لدينا شيفرة HTML الآتية:

<article class="post">
  <header>
    <!-- … -->
    <p>Tags: <a href="..." class="tag">irrelevant</a></p>
  </header>
  <!-- … -->
</article>

فقد تجد ما يلي في شيفرة CSS:

article.post {
  // ... ستُذكَر القواعد الأخرى هنا
  header {
    // ...
    p {
      // ...
      a.tag {
        background: #ff0;
      }
    }
  }
}

الجانب السلبي الرئيسي لهذا هو أنَّ مُحدِّدات CSS الناتجة هي مُحدِّدات مخصصة جدًا، وشرحنا من قبل أنَّ علينا تفادي استخدامها. هنالك سلبيات أخرى للاستخدام المفرط للتشعّب، والتي ذُكِرَت في هذا الدرس.
باختصار: لا تجعل تشعّب مُحدِّدات CSS في مفسرات CSS يولِّد قواعد لن تفكر في كتابتها يدويًا دون مُفسِّر.

استخدام include أو استخدام extend؟

ميزة أخرى مفيدة لمُفسِّرات CSS تدعى «mixins»، وهي مجموعة من قواعد CSS القابلة لإعادة الاستخدام، فمثلًا لنقل أننا نريد تنسيق الأزرار (buttons)، وأغلبية الأزرار لها نفس خاصيات CSS الأساسية؛ لذا يمكننا إنشاء mixin كما يلي في Less:

.button-base() {
  padding: 1em;
  border: 0;
}

ثم إنشاء قاعدة كالآتية:

.button-primary {
  .button-base();
  background: blue;
}

والتي ستولِّد شيفرة CSS:

.button-primary {
  padding: 1em;
  border: 0;
  background: blue;
}

كما ترى، من المفيد جدًا إعادة هيكلة (واستخدام) الشيفرات المكررة.
وإلى جانب «تضمين» (including) بُنية mixin، هنالك خيارٌ آخر هو «توسعة» (extending) أو «وراثة» تلك البنية (يختلف المصطلح المستعمل اعتمادًا على الأداة المستخدمة). والتي ستَدمِج عدة مُحدِّدات في نفس القاعدة.
لنشاهد مثالًا عمليًا عن توسعة بنية mixin السابقة (أي ‎.button-base):

.button-primary {
  &:extend(.button-base)
  background: blue;
}

.button-danger {
  &:extend(.button-base)
  background: red;
}

والتي ستحوّل إلى شيفرة CSS الآتية:

.button-primary, .button-danger {
  padding: 1em;
  border: 0;
}

.button-primary { background: blue; }
.button-danger { background: red; }

بعض المقالات والدروس الموجودة على الويب تخبرنا أن نستخدم طريقة «include» فقط، والأخرى تطلب منا استخدام طريقة «extend» فقط؛ لكن الواقع هو أنَّ كلا الطريقتين ستنتجان شيفرات CSS مختلفة، وليس من الخطأ استخدام أي واحدة منهما، لكن قد يُفضَّل استخدام إحداهما على الأخرى في بعض الحالات.
كيف تختار بينهما؟ أكرِّر أنَّ قاعدة «هل ستكتب هذه الشيفرة يدويًا» تنطبق هنا.

الخلاصة

أرجو أن يؤثر هذا الدرس عليك ويجعل طريقة كتابتك لشيفرات CSS أفضل؛ تذكَّر ما قلتُ لك سابقًا: CSS هي شيفرات، ويجب أن تعاملها بنفس طريقة معاملتك لبقية الشيفرات. فإن أعطيتها الاهتمام اللازم فسترد لك الجميل :-) .
ترجمة -وبتصرّف- للمقال CSS coding techniques لصاحبه Belén Albeza





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن