منهجية BEM لتسمية محددات CSS

هل سبق لك قراءة ملف CSS لتجد في أسماء المحددات (Selectors) خليطاً من الشرطات العلوية ”–“ والسفلية ”__“؟

إن لم تكن قد فعلت فعلى الأغلب أنك ستصادف هذه الحالة عما قريب. لكن ما معنى هذه الطريقة في التسمية؟ هل هي مجرد عمل مطور كسول لدرجة لا يستطيع معها المحافظة على محرف فاصل واحد؟ أم أن هنالك سبباً منطقياً وراء كل ذلك؟

منهجية BEM لتسمية محددات CSS

البحث سيدلنا في النهاية إلى BEM و نيكولاس غالاغر.

BEM —اختصار لكلمات كتلة (Block) وعنصر (Element) ومعدّل (Modifier)— هي منهجية تسمية تستخدم خلال تطوير الواجهات (Front-end)، خرج بها فريق Yandex. إنها طريقة ذكية لتسمية المحددات (Selectors) في CSS لإعطائها معنىً دلالياً واضحاً باتباع مجموعة قواعد قليلة لكنها صارمة، مما يجعلها مناسبة جداً عند العمل ضمن فريق على مشاريع قد تطول فترة من الزمن.

القواعد التي سنذكرها هنا قام نيكولاس غالاغر باشتقاقها وتحسينها عن قواعد BEM الأصلية. لدينا بشكل أساسي القواعد التالية:

.block {}
.block__element {}
.block--modifier {}
  • block. يعبر عن اسم مكون مميز ومتكامل.
  • block__element. هو عنصر ضمن المكون ولا يفترض أن يتواجد خارجه.
  • block–modifier. هو تنويعة أو شكل آخر لتنسيق المكون.

استخدام شرطتين (علويتين أو سفليتين) عوضاً عن واحدة في التسمية يسمح لنا باستخدام الشرطة المفردة ضمن اسم المكون الكتلة الأساسية (المكون). على سبيل المثال:

.site-search {} /* Block */
.site-search__field {} /* Element */
.site-search--full {} /* Modifier */

الهدف من استخدام BEM هو مساعدة أعضاء الفريق على فهم وظيفة المحددات عبر قراءة اسمها ببساطة. وبقراءة الأسماء يحصل على صورة كاملة لكافة التنسيقات، فيوجد لدينا مكونات أو كتل في المستوى الأعلى (blocks)، يمكن لكل منها أن يمتلك أبناء أو عناصر (elements)، كما يمكن أن توجد تنويعات أو معدلات لكل منها (modifiers). فكر كيف تترابط المحدد التالية مع بعضها لتعطيك صورة كاملة عن المكون:


.person {}
.person__hand {}
.person--female {}
.person--female__hand {}
.person__hand--left {}

المستوى الأعلى في هذه الحالة هو الشخص person، قد يمتلك أجزاء فرعية مثل اليد hand، وقد يكون له أنواع مختلفة بحسب الجنس مثلاً female. وبدورها يمكن للتنويعات أن تعيد تعريف الأجزاء الفرعية (female__hand) كما يمكن أن تمتلك الأجزاء تنويعات مختلفة (hand–left).

لنعد تعريف المحددات السابقة باستخدام الطريقة القديمة:

.person {}
.hand {}
.female {}
.female-hand {}
.left-hand {}

قد تكون واضحة إلى حد ما (بما أننا نعرف الغرض منها) لكن وظائفها والروابط بينها مبهمة. خذ الأنثى female على سبيل المثال، عن ماذا تعبر؟ وماذا عن اليد hand؟ هل هي يد شخص؟ يد ساعة الحائط؟

استطعنا باستخدام BEM أن نعطي المزيد الوضوح وننشئ روابط منطقية باستخدام الأسماء فقط، وهذا رائع!

لنحاول صياغة شيفرة HTML لمكون البحث الذي كنا نتحدث عنه قبل قليل:

<form class="site-search full">
  <input type="text" class="field">
  <input type="Submit" value ="Search" class="button">
</form>

الأسماء غير واضحة ولا تعطينا الكثير من المعلومات عن الغرض منها، قد نتمكن من فهمها إلى حد ما لكن شخصاً يقرأ الشيفرة للمرة الأولى سيقف مرتبكاً أكثر من حرباء على قوس قزح!

لنعد التعرف بتطبيق قواعد BEM هذه المرة:

<form class="site-search site-search--full">
  <input type="text" class="site-search__field">
  <input type="Submit" value ="Search" class="site-search__button">
</form>

نستطيع أن نرى من القراءة الأولى أننا نملك هنا مكوناً اسمه site-search يحوي عنصراً اسمه site-search__field وعنصراً آخر اسمه site-search__button ويمتلك تنسيقاً آخر site-search–full

لنشاهد مثالاً آخر. إذا كان لديك اطلاع على CSS غرضية التوجه (OOCSS) فلا بد أنك تعرف غرض المحتوى media object، يمكن تنسيقه وفق BEM كما يلي:

.media {}
.media__img {}
.media__img--rev {}
.media__body {}

مرة أخرى نستطيع بنظرة واحدة أن نستنتج وجود مكون اسمه media يمتلك عنصرين فرعيين img و body يجب أن يتواجدا ضمنه وليس خارجه، ويوجد تنويعة لإعطاء تنسيق مختلف لعنصر img باسم img–rev. استقينا كل هذه المعلومات من التسميات فقط!

باستخدام BEM نستطيع أيضاً التعاطي بشكل أفضل مع حالات مشابهة لما يلي:

<div class="media">
  <img src="logo.png" alt="Foo Corp logo" class="img-rev">
  <div class="body">
    <h3 class="alpha">Welcome to Foo Corp</h3>
    <p class="lede">Foo Corp is the best, seriously!</p>
  </div>
</div>

بالنظر إلى الشيفرة السابقة، لا نستطيع أن نرى الارتباط بين اسمي المحددين media و alpha! هل هما مرتبطان أساساً؟ ماذا عن body و lede؟ أو img-rev مع media؟

إذا لم يكن لدينا فكرة مسبقة عن غرض المحتوى media object فلن نستطيع تمييز أسماء المحددات التي تلزم لعمله عن تلك الإضافية أو الاختيارية. لنعد الكتابة باستخدام BEM:

<div class="media">
  <img src="logo.png" alt="Foo Corp logo" class="media__img--rev">
  <div class="media__body">
    <h3 class="alpha">Welcome to Foo Corp</h3>
    <p class="lede">Foo Corp is the best, seriously!</p>
  </div>
</div>

نستطيع فوراً أن نرى أن media هو المكون الأساسي، يحوي ضمنه عنصراً معدّلاً هو media__img–rev وعنصراً غير معدّل هو media__body، هذا مفيدٌ للغاية!

ولكنه قبيح!

إحدى الحجج المضادة لاستخدام BEM تعتمد على قبح الشيفرة الناتجة، لكن أجرأ على القول أنك إن اعتمدت على مظهر الشيفرة لتقرر اعتمادها فقد فاتك الهدف تماماً. لو تسبب استخدام منهجية ما بجعل الشيفرة صعبة القراءة والصيانة بشكل فعلي ومن غير مبرر، فلديك كل الحق في تجاهلها. لكن لو كنت تظن ببساطة أنها تتسبب في جعل شكل الشيفرة يبدو غريباً مع وجود هدف وظيفي من وراء ذلك، فقد يكون عليك أن تفكر ملياً قبل أن تخرجها من اللعبة!

أوافق تماماً على أن الشيفرة الناتجة عن استخدام BEM غريبة الشكل، لكن فوائدها من ناحية سرعة فهم الشيفرة وربط الأجزاء ببعضها تفوق هذه السلبية بكثير. قد تتطلب المزيد من الكتابة، لكن خذ بعين الاعتبار أن جميع محررات النصوص البرمجية اليوم تتمتع بميزة الإكمال التلقائي (Autocomplete) كما أن الزيادة في حجم ملفات الشيفرة يمكن عكسها باستخدام ضغط gzip، وستحصل في النهاية على منهجية تسمية غاية في القوة ذات قاعدة مستخدمين تزداد يوماً بعد يوم.

BEM ليست لجميع الأغراض!

مبدئياً أنا من المشجعين بقوة لتبني BEM وضمها إلى سير عمل فريقك، فهي تنظم العديد من الأمور وتصل العديد من النقاط بالنسبة للفريق، أو بالنسبة لك على الأقل في حال احتجت للعودة إلى المشروع.

ولكن BEM، شأنها شأن أي تقنية أخرى، ليست مناسبة لجميع الحالات. خذ على سبيل المثال:

.caps { text-transform: uppercase; }

المحدد هنا لا يقع ضمن مكون محدد ولا حاجة لتعقيد الأمور، يمكننا أن ندعه كمحدد منفصل عن باقي الشيفرة.

إليك مثالاً آخر قد يكون مربكاً بعض الشي:

.site-logo {}

يمكننا بالطبع أن نستخدم BEM لتنفيذ ذلك كما يلي:

.header {}
.header__logo {}

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

مثالٌ آخر:

<div class="content">
  <h1 class="content__headline">Lorem ipsum dolor...</h1>
</div>

يمكننا هنا ببساطة أن نسمي محدد العنوان headline. ولكن ذلك يعتمد على طريقة عملنا، هل العنوان جزء حيوي لعمل المكوّن بشكل متكامل؟ أم أنه صادف وجوده في هذا المكان؟ في الحالة الثانية لست بحاجة لاستخدام BEM.

كل عنصر ضمن الصفحة يحتمل أن يتبع قواعد BEM. لنعد قليلاً إلى مثال الشعار، قد نحتاج لإدراج الشعار بشكل احتفالي خلال موسم الأعياد، وهنا قد تساعدنا فكرة التنويعات (modifiers) بالشكل التالي:

.site-logo {}
.site-logo--xmas {}

الجزء الأصعب من BEM هو معرفة أين ومتى يجب استخدامها، وهذا لا يأتي إلا من خلال التجربة وزيادة الخبرة.

كلمة أخيرة

هذه هي BEM، منهجية تسمية مفيدة وفعالة وبسيطة ستجعل الشيفرة البرمجية للواجهات التي تقوم بتنفيذها أسهل للقراءة والتطوير والتوسيع ضمن إطار صارم من القواعد للمحافظة على الوضوح.

بالرغم من غرابتها، تستحق BEM أن تكون جزءاً من أي مشروع تقوم بالعمل عليه من الآن فصاعداً.

المصدر

مترجم بتصرف عن MindBEMding – getting your head ’round BEM syntax

محمود الدعاس

من مواليد دمشق. ابتدأ بعد التخرج كمبرمج ويب عام 2005 مع شركة إيميا، انتقل بعدها إلى شركة تكنوليد للأتمتة المتكاملة ومنها إلى شقيقتها أتمتة للحلول المتقدمة كمصمم غرافيك ومصمم ومطور ويب. أسس مع مجموعة من زملاء الدراسة موقع HOMELESS-PRO.com لنشر قصص مصورة باللغة العربية للشباب، و Guestra كوكالة تصميم وتطوير.

مواضيع الكاتبموقع الكاتب

لمتابعة الكاتب:
TwitterFacebookPinterest

One thought on “منهجية BEM لتسمية محددات CSS

أضف تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *