BEM للمبتدئين: لماذا تحتاج BEM
نشرت: 2022-03-10يجعل BEM كودك قابلاً للتطوير وإعادة الاستخدام ، وبالتالي زيادة الإنتاجية وتسهيل العمل الجماعي. حتى لو كنت العضو الوحيد في الفريق ، يمكن أن يكون BEM مفيدًا لك. ومع ذلك ، يعتقد العديد من المطورين أن نهج النظام مثل BEM يضع حدودًا إضافية على مشروعهم ويجعل مشروعك مثقلًا ومرهقًا وبطيئًا.
سنقوم بتجميع جميع الجوانب الرئيسية لـ BEM في شكل مكثف. تساعدك هذه المقالة على فهم الأفكار الأساسية لـ BEM في 20 دقيقة فقط ، ورفض الأحكام المسبقة بأن نهج النظام يضر بمشروعك.
يتكون Big BEM من المنهجية والتقنيات والمكتبات والأدوات . في هذه المقالة ، سنتحدث أكثر عن المنهجية نفسها لأنها خبرة مركزة لعدد كبير من المطورين وهي تجلب منهجًا منظمًا لأي مشروع.
من أجل عرض بعض الحالات العملية لـ BEM ، سنتطرق إلى تقنيات BEM ونتخطى المكتبات والأدوات تمامًا.
من النظرية إلى التطبيق:
- الأسباب الرئيسية لعدم استخدام أي محددات باستثناء الفئات
- أساسيات BEM
- الكتل والعناصر
- المعدلات والخلطات
- كتل في هيكل الملف
- المزايا غير الواضحة للمنهجية
- حالة عملية: BEM ليس فقط لـ CSS
- BEM هو نظام قابل للتخصيص
إذن ، هل BEM بطل أم شرير؟ الأمر متروك لك! لكن أولاً ، اقرأ المقال.
الأسباب الرئيسية لعدم استخدام أي محددات باستثناء الفئات
تتمثل إحدى القواعد الأساسية لمنهجية BEM في استخدام محددات الفئات فقط. في هذا القسم ، سنشرح السبب.
- لماذا لا نستخدم المعرفات؟
- لماذا لا نستخدم محددات العلامات؟
- لماذا لا نستخدم المحدد العام؟
- لماذا لا نستخدم إعادة تعيين CSS؟
- لماذا لا نستخدم المحددات المتداخلة؟
- لماذا لا ندمج علامة وفئة في محدد؟
- لماذا لا نستخدم المحددات المجمعة-
- لماذا لا نستخدم محددات السمات؟
نحن لا نستخدم المعرفات (محددات الهوية)
يوفر المعرف اسمًا فريدًا لعنصر HTML. إذا كان الاسم فريدًا ، فلا يمكنك إعادة استخدامه في الواجهة. هذا يمنعك من إعادة استخدام الكود.
المفاهيم الخاطئة الشائعة
- المعرفات مطلوبة لاستخدام JavaScript.
يمكن أن تعمل المتصفحات الحديثة مع المعرفات أو الفئات. تتم معالجة أي نوع من المحددات بنفس المعدل في المتصفح. - يتم استخدام المعرفات مع
<label>
.
إذا وضعت<label>
داخل عنصر تحكم ، فلن تحتاج إلى معرف. بدلاً من<input id="ID"><label for="ID">Text</label>
، ما عليك سوى استخدام<label><input type="...">Text</label>
.
نحن لا نستخدم محددات العلامات
ترميز صفحة HTML غير مستقر: يمكن للتصميم الجديد تغيير تداخل الأقسام أو مستويات العناوين (على سبيل المثال ، من <h1>
إلى <h3>
) أو تحويل الفقرة <p>
إلى علامة <div>
. سيؤدي أي من هذه التغييرات إلى كسر الأنماط المكتوبة للعلامات. حتى لو لم يتغير التصميم ، فإن مجموعة العلامات محدودة. لاستخدام تخطيط موجود في مشروع آخر ، يجب عليك حل التعارضات بين الأنماط المكتوبة لنفس العلامات.
لا يمكن لمجموعة موسعة من العلامات الدلالية أن تلبي جميع احتياجات التخطيط أيضًا.
مثال على ذلك عندما يحتوي رأس الصفحة على شعار. يؤدي النقر فوق الشعار إلى فتح الصفحة الرئيسية للموقع ( index
). يمكنك ترميزها بالعلامات باستخدام علامة <img>
للصورة وعلامة <a>
للارتباط.
<header> <a href="/"> <img src="img.logo.png" alt="Logo"> </a> </header>
للتمييز بين رابط الشعار والرابط العادي في النص ، تحتاج إلى أنماط إضافية. الآن قم بإزالة التسطير واللون الأزرق من رابط الشعار:
header a { ... }
لا يلزم إظهار ارتباط الشعار على الصفحة الرئيسية ، لذلك قم بتغيير ترميز صفحة الفهرس:
<header> <!-- the <a> tag is replaced with <span> --> <span> <img src="img.logo.png" alt="Logo"> </span> </header>
لا تحتاج إلى إزالة التسطير واللون الأزرق لعلامة <span>
. لنضع قواعد عامة لرابط الشعار من صفحات مختلفة:
header a, header span { ... }
للوهلة الأولى ، يبدو هذا الرمز على ما يرام ، لكن تخيل ما إذا كان المصمم قد أزال الشعار من التخطيط. لا تساعدك أسماء المحددات في فهم الأنماط التي يجب إزالتها من المشروع الذي يحمل الشعار. لا يُظهر محدد "الرأس أ" الاتصال بين الارتباط والشعار. يمكن أن ينتمي هذا المحدد إلى الارتباط الموجود في قائمة الرأس أو ، على سبيل المثال ، إلى الرابط المؤدي إلى ملف تعريف المؤلف. يمكن أن ينتمي محدد "header span" إلى أي جزء من الرأس.
لتجنب الالتباس ، ما عليك سوى استخدام محدد فئة logo
لكتابة أنماط الشعار:
.logo { ... }
نحن لا نستخدم CSS Reset
إعادة تعيين CSS عبارة عن مجموعة من قواعد CSS العامة التي تم إنشاؤها للصفحة بأكملها. تؤثر هذه الأنماط على جميع عقد التخطيط ، وتنتهك استقلالية المكونات ، وتجعل من الصعب إعادة استخدامها.
في BEM ، لا يتم استخدام "إعادة التعيين" و "التطبيع" حتى لكتلة واحدة. تؤدي إعادة التعيين والتطبيع إلى إلغاء الأنماط الحالية واستبدالها بأنماط أخرى ، والتي سيتعين عليك تغييرها وتحديثها لاحقًا على أي حال. نتيجة لذلك ، يتعين على المطور كتابة أنماط تتجاوز تلك التي تم إعادة تعيينها للتو.
نحن لا نستخدم المحدد العام ( *
)
يشير المحدد العام إلى أن المشروع يتميز بنمط يؤثر على جميع العقد في التخطيط. هذا يحد من إعادة استخدام التخطيط في مشاريع أخرى:
- يجب عليك بالإضافة إلى ذلك نقل الأنماط بعلامة النجمة إلى المشروع. لكن في هذه الحالة ، قد يؤثر المحدد العام على الأنماط في المشروع الجديد.
- يجب إضافة الأنماط ذات علامة النجمة إلى التخطيط الذي تقوم بنقله.
بالإضافة إلى ذلك ، يمكن أن يجعل المحدِّد العام رمز المشروع غير متوقع. على سبيل المثال ، يمكن أن يؤثر على أنماط مكونات المكتبة العالمية.
الأنماط الشائعة لا توفر لك الوقت. غالبًا ما يبدأ المطورون بإعادة تعيين جميع الهوامش للمكونات ( * { margin: 0; padding: 0; }
) ، لكنهم ما زالوا يقومون بتعيينها كما هو الحال في التخطيط (على سبيل المثال ، margin: 12px; padding: 30px;
).
نحن لا نستخدم المحددات المتداخلة
تزيد المحددات المتداخلة من اقتران الكود وتجعل من الصعب إعادة استخدام الكود.
لا تحظر منهجية BEM المحددات المتداخلة ، لكنها توصي بعدم استخدامها كثيرًا. على سبيل المثال ، يعد التداخل مناسبًا إذا كنت بحاجة إلى تغيير أنماط العناصر اعتمادًا على حالة الكتلة أو النسق المخصص لها.
.button_hovered .button__text { text-decoration: underline; } .button_theme_islands .button__text { line-height: 1.5; }
نحن لا نستخدم المحددات المجمعة
تعتبر المحددات المجمعة أكثر تحديدًا من المحددات الفردية ، مما يجعل إعادة تعريف الكتل أكثر صعوبة.
ضع في اعتبارك الكود التالي:
<button class="button button_theme_islands">...</button>
لنفترض أنك قمت بتعيين قواعد CSS في محدد .button.button_theme_islands
للقيام بالكتابة بشكل أقل. ثم تضيف المُعدِّل "النشط" إلى الكتلة:
<button class="button button_theme_islands button_active">...</button>
لا يقوم المحدد .button_active
بإعادة تعريف خصائص الكتلة المكتوبة كـ .button.button_theme_islands
لأن .button.button_theme_islands
.button_active
لإعادة تعريفه ، .button
مُحدِّد مُعدِّل الكتلة مع مُحدِّد .button.button_theme_islands
.
.button.button_theme_islands {} .button.button_active {}
إذا كنت تستخدم محددات فئة بسيطة ، فلن تواجه مشكلات في إعادة تعريف الأنماط:
.button_theme_islands {} .button_active {} .button {}
نحن لا نجمع بين العلامة والفئة في المحدد
يؤدي الجمع بين علامة وفئة في نفس المحدد (على سبيل المثال ، button.button
) إلى جعل قواعد CSS أكثر تحديدًا ، لذلك يصعب إعادة تعريفها.
ضع في اعتبارك الكود التالي:
<button class="button">...</button>
لنفترض أنك قمت بتعيين قواعد CSS في button.button
. ثم تضيف المعدل active
إلى الكتلة:
<button class="button button_active">...</button>
لا يقوم المحدد .button_active
بإعادة تعريف خصائص الكتلة المكتوبة كـ button.button
لأن الزر. button.button
أكثر تحديدًا من .button_active
. لجعلها أكثر تحديدًا ، يجب أن تجمع بين محدد معدل الكتلة button.button_active
.
مع تطور المشروع ، قد ينتهي بك الأمر input.button
تحتوي على زر span.button
أو زر مفتاح أو a.button
محدد. في هذه الحالة ، ستتطلب كل مُعدِّلات كتلة button
وجميع عناصرها المتداخلة أربعة تصريحات مختلفة لكل حالة.
الاستثناءات الممكنة
في حالات نادرة ، تسمح المنهجية بدمج محددات العلامات والفئات. على سبيل المثال ، يمكن استخدام هذا لتعيين نمط التعليقات في أنظمة CMS التي لا يمكنها إنشاء التنسيق الصحيح.
يمكنك استخدام التعليق لكتابة نص أو إدراج صور أو إضافة ترميز. لجعلها تتطابق مع تصميم الموقع ، يمكن للمطور تحديد الأنماط مسبقًا لجميع العلامات المتاحة للمستخدم وتسلسلها إلى الكتل المتداخلة:
<div class="content"> ... <!-- the user's text --> </div> CSS rules: .content a { ... } .content p { font-family: Arial, sans-serif; text-align: center; }
نحن لا نستخدم محددات السمات
محددات السمات أقل إفادة من محددات الفئة. كدليل ، ضع في اعتبارك مثالًا مع نموذج بحث في الرأس:
<header> <form action="/"> <input name="s"> <input type="submit"> </form> </header>
حاول استخدام سمات المحدد لكتابة أنماط النموذج:
header input[type=submit], header input[type=checkbox] { width: auto; margin-right: 20px; } header input[type=checkbox] { margin: 0; }
في هذا المثال ، لا يمكنك التأكد من اسم المحدد من أن الأنماط تنتمي إلى نموذج البحث. استخدام الفصول يجعل الأمر أكثر وضوحا. لا توجد قيود تمنعك من الكتابة بوضوح في الفصول الدراسية. على سبيل المثال ، يمكنك كتابتها على النحو التالي:
.form .search { ... }
أصبح الرمز الآن أقل غموضًا ، ومن الواضح أن الأنماط تنتمي إلى نموذج البحث.
لكن المحددات المتداخلة لا تزال تجعل قواعد CSS أكثر تحديدًا وتمنعك من نقل التخطيط بين المشاريع. للتخلص من التعشيش ، استخدم مبادئ BEM.
الملخص : class
هو المحدد الوحيد الذي يسمح لك بعزل أنماط كل مكون في المشروع ؛ زيادة سهولة قراءة الكود ولا تحد من إعادة استخدام التخطيط.
عزل أنماط CSS هو نقطة البداية الأكثر شيوعًا لرحلة BEM. ولكن هذا هو أقل ما يمكن أن يقدمه لك BEM. لفهم كيفية ترتيب المكونات المستقلة المعزولة في BEM ، تحتاج إلى معرفة المفاهيم الأساسية ، مثل Block و Element و Modifier و Mix. لنفعل هذا في القسم التالي.
أساسيات BEM
- الكتل والعناصر
- المعدلات والخلطات
- كتل في هيكل الملف
الكتلة والعناصر
منهجية BEM هي مجموعة من القواعد العامة التي يمكن تطبيقها بغض النظر عن التقنيات المستخدمة ، مثل CSS أو Sass أو HTML أو JavaScript أو React.
يساعد BEM في حل المهام التالية:
- إعادة استخدام التخطيط ؛
- نقل أجزاء التخطيط بأمان داخل المشروع ؛
- نقل التخطيط النهائي بين المشاريع ؛
- إنشاء رمز ثابت ويمكن التنبؤ به وواضح ؛
- تقليل وقت تصحيح المشروع.
في مشروع BEM ، تتكون الواجهة من كتل يمكن أن تتضمن عناصر. الكتل هي مكونات مستقلة للصفحة. لا يمكن أن يوجد عنصر خارج الكتلة ، لذا ضع في اعتبارك أن كل عنصر يمكن أن ينتمي إلى كتلة واحدة فقط.
يرمز الحرفان الأولان في BEM إلى أقفال B و E. دائمًا ما يكون اسم الكتلة فريدًا. يقوم بتعيين مساحة الاسم للعناصر ويوفر اتصالاً مرئيًا بين أجزاء الكتلة. أسماء الكتل طويلة ولكنها واضحة لإظهار الاتصال بين المكونات ولتجنب فقد أي أجزاء من هذه المكونات عند نقل التخطيط.
لمعرفة القوة الكاملة لتسمية BEM ، ضع في اعتبارك هذا المثال مع نموذج. وفقًا لمنهجية BEM ، يتم تنفيذ النموذج باستخدام قالب form
. في HTML ، يتم تضمين اسم الكتلة في سمة class
:
<form class="form" action="/">
تعتبر جميع أجزاء النموذج (قالب form
) التي لا معنى لها من تلقاء نفسها عناصره. لذا فإن مربع البحث ( search
) والزر ( submit
) هما عنصران من عناصر كتلة form
. تشير الفئات أيضًا إلى أن العنصر ينتمي إلى الكتلة:
<form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
لاحظ أنه يتم فصل اسم الكتلة عن اسم العنصر بفاصل خاص. في نظام التسمية الكلاسيكي BEM ، يتم استخدام شرطين سفلية كفاصل. يمكن أن يعمل أي شيء كفاصل. هناك اصطلاحات تسمية بديلة ، ويختار كل مطور ما يناسبه. الشيء المهم هو أن الفواصل تسمح لك بتمييز الكتل عن العناصر والمعدلات برمجيًا.
توضح أسماء المحددات أنه من أجل نقل النموذج إلى مشروع آخر ، تحتاج إلى نسخ جميع مكوناته:
.form__search {} .form__submit {}
يؤدي استخدام الكتل والعناصر لأسماء الفئات إلى حل مشكلة مهمة: يساعدنا في التخلص من المحددات المتداخلة. جميع المحددات في مشروع BEM لها نفس الوزن. هذا يعني أنه من الأسهل بكثير إعادة تعريف الأنماط المكتوبة وفقًا لـ BEM. الآن ، لاستخدام نفس النموذج في مشروع آخر ، يمكنك فقط نسخ تخطيطه وأنماطه.
تتمثل فكرة تسمية مكونات BEM في أنه يمكنك تحديد الاتصال بين الكتلة وعناصرها بشكل صريح.
المعدلات والخلطات
رسميًا ، يرمز الحرف "M" إلى M odifier ، ولكنه يشير أيضًا إلى فكرة أكثر أهمية في BEM: "mix". تقوم كل من المعدلات والخلطات بإجراء تغييرات على الكتلة وعناصرها. دعونا نلقي نظرة فاحصة على هذا.
الصفات التعريفية
يعرّف المعدل مظهر وحالة وسلوك كتلة أو عنصر. إضافة المعدلات أمر اختياري. تتيح لك المُعدِّلات الجمع بين ميزات الكتلة المختلفة ، حيث يمكنك استخدام أي عدد من المُعدِّلات. لكن لا يمكن تعيين قيم مختلفة لنفس المُعدِّل لكتلة أو عنصر.
دعنا نستكشف كيف تعمل المعدلات.
تخيل أن المشروع يحتاج إلى نفس نموذج البحث كما في المثال أعلاه. يجب أن يكون لها نفس الوظائف ولكن تبدو مختلفة (على سبيل المثال ، يجب أن تختلف نماذج البحث في رأس الصفحة وتذييلها). أول شيء يمكنك القيام به لتغيير مظهر النموذج هو كتابة أنماط إضافية:
header .form {} footer .form {}
محدد header .form
له وزن أكبر من محدد form
، مما يعني أن إحدى القواعد ستتجاوز الأخرى. ولكن كما ناقشنا ، تزيد المحددات المتداخلة من اقتران الكود وتجعل إعادة الاستخدام أمرًا صعبًا ، لذا فإن هذا الأسلوب لا يعمل بالنسبة لنا.
في BEM ، يمكنك استخدام معدل لإضافة أنماط جديدة إلى الكتلة:
<!-- Added the form_type_original modifier--> <form class="form form_type_original" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
يشير السطر <form class="form form_type_original"></form>
إلى أن الكتلة قد تم تعيين معدِّل type
بالقيمة original
لها. في المخطط الكلاسيكي ، يتم فصل اسم المعدل عن اسم الكتلة أو العنصر بشرطة سفلية.
يمكن أن يكون للنموذج لون أو حجم أو نوع أو سمة تصميم فريدة. يمكن ضبط كل هذه المعلمات بمعدِّل:
<form class="form form_type_original form_size_m form_theme_forest">
<form class="form form_type_original form_size_m form_theme_forest">
يمكن أن يبدو الشكل نفسه مختلفًا ولكن يظل بالحجم نفسه:
<form class="form form_type_original form_size_m form_theme_forest"></form> <form class="form form_type_original form_size_m form_theme_sun"></form>
لكن المحددات لكل معدِّل ستظل لها نفس الوزن:
.form_type_original {} .form_size_m {} .form_theme_forest {}
هام : يحتوي المعدل على أنماط إضافية فقط تغير تنفيذ الكتلة الأصلية بطريقة ما. يسمح لك هذا بتعيين مظهر الكتلة العامة مرة واحدة فقط ، وإضافة تلك الميزات التي تختلف عن رمز الكتلة الأصلي إلى أنماط المُعدِّل.
.form { /* universal block styles */ } .form_type_original { /* added styles */ }
هذا هو السبب في أن المُعدِّل يجب أن يكون دائمًا على نفس عقدة DOM مع الكتلة والعنصر المرتبط به.
<form class="form form_type_original"></form>
يمكنك استخدام المعدِّلات لتطبيق المكونات العامة في حالات محددة للغاية. لا يتغير رمز الكتلة والعنصر. يتم إنشاء مجموعة المعدلات الضرورية على عقدة DOM.
يمزج
يتيح لك المزيج تطبيق نفس التنسيق على عناصر HTML مختلفة والجمع بين سلوك وأنماط العديد من الكيانات مع تجنب تكرار التعليمات البرمجية. يمكنهم استبدال كتل التجميع المجردة.
يعني المزيج أنك تستضيف عدة كيانات BEM (كتل وعناصر ومعدلات) على عقدة DOM واحدة. على غرار المعدلات ، يتم استخدام الخلطات لتغيير الكتل. لنلقِ نظرة على بعض الأمثلة التي توضح متى يجب استخدام مزيج.
يمكن أن تختلف الكتل ليس فقط بصريًا ولكن أيضًا من الناحية المعنوية. على سبيل المثال ، نموذج البحث واستمارة التسجيل واستمارة طلب الكعك كلها أشكال. في التخطيط ، يتم تنفيذها باستخدام كتلة "النموذج" ولكن ليس لديهم أي أنماط مشتركة. من المستحيل التعامل مع هذه الاختلافات باستخدام معدل. يمكنك تحديد الأنماط الشائعة لمثل هذه الكتل ولكنك لن تتمكن من إعادة استخدام الكود.
.form, .search, .register { ... }
يمكنك استخدام مزيج لإنشاء كتل مختلفة لغويًا لنفس النموذج:
<form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
يصف محدد فئة .form
. جميع الأنماط التي يمكن تطبيقها على أي نموذج (ترتيب أو بحث أو تسجيل):
.form {}
يمكنك الآن عمل نموذج بحث من النموذج العام. للقيام بذلك ، قم بإنشاء فئة search
إضافية في المشروع. هذه الفئة ستكون مسؤولة فقط عن البحث. لدمج أنماط وسلوك فئات .form
و. .search
، ضع هذه الفئات في عقدة DOM واحدة:
<form class="form search" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>
في هذه الحالة ، تعتبر فئة .search
كتلة منفصلة تحدد السلوك. لا يمكن أن تحتوي هذه الكتلة على مُعدِّلات مسؤولة عن النموذج والسمات والأحجام. هذه المعدلات تنتمي بالفعل إلى الشكل العام. يساعد المزيج على الجمع بين أنماط وسلوك هذه الكتل.
لنأخذ مثالاً آخر حيث يتم تغيير دلالات المكون. فيما يلي قائمة تنقل في رأس الصفحة حيث تكون جميع الإدخالات عبارة عن روابط:
<nav class="menu"> <a class="link" href=""></a> <a class="link" href=""></a> <a class="link" href=""></a> </nav>
تم تنفيذ وظيفة الارتباط بالفعل في كتلة link
، ولكن يجب أن تختلف روابط القائمة بصريًا عن الروابط الموجودة في النص. هناك عدة طرق لتغيير روابط القائمة:
- أنشئ معدِّل إدخال قائمة يحول الإدخال إلى رابط:
<nav class="menu"> <a class="menu__item menu__item_link" href=""></a> <a class="menu__item menu__item_link" href=""></a> <a class="menu__item menu__item_link" href=""></a> </nav>
في هذه الحالة ، لتنفيذ المُعدِّل ، يجب نسخ سلوك وأنماط كتلة `link`. سيؤدي هذا إلى تكرار الكود. - استخدم مزيجًا من الكتلة العامة "link" والعنصر "العنصر" في كتلة "القائمة":
<nav class="menu"> <a class="link menu__item" href=""></a> <a class="link menu__item" href=""></a> <a class="link menu__item" href=""></a> </nav>
باستخدام مزيج من كيانين BEM ، يمكنك الآن تنفيذ وظيفة الارتباط الأساسية من كتلة "link" وقواعد CSS الإضافية من كتلة "القائمة" ، وتجنب تكرار الكود.
الهندسة الخارجية وتحديد المواقع: التخلي عن أغلفة HTML المجردة
تُستخدم عمليات المزج لوضع كتلة بالنسبة إلى الكتل الأخرى أو لوضع عناصر داخل كتلة. في BEM ، يتم تعيين الأنماط المسؤولة عن الهندسة وتحديد المواقع في الكتلة الأصلية. لنأخذ كتلة قائمة عالمية يجب وضعها في الرأس. في التخطيط ، يجب أن يكون للكتلة مسافة بادئة 20 بكسل من الكتلة الأصلية.
لهذه المهمة عدة حلول:
- كتابة الأنماط مع المسافات البادئة لكتلة القائمة:
.menu { margin-left: 20px; }
في هذه الحالة ، لم تعد كتلة "القائمة" عامة. إذا كان عليك وضع القائمة في تذييل الصفحة ، فسيتعين عليك تحرير الأنماط لأنه من المحتمل أن تكون المسافات البادئة مختلفة. - قم بإنشاء معدّل كتلة القائمة:
<div> <ul class="menu menu_type_header"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
.menu_type_header { margin-left: 20px; } .menu_type_footer { margin-left: 30px; }
في هذه الحالة ، سيتضمن المشروع نوعين من القوائم ، على الرغم من أن هذا ليس هو الحال. القائمة تبقى كما هي. - حدد الموضع الخارجي للكتلة: قم بتداخل كتلة "القائمة" في الغلاف المجرد (على سبيل المثال ، كتلة "الالتفاف") مع تعيين جميع المسافات البادئة:
<div class="wrap"> <ul class="menu"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
لتجنب إغراء إنشاء معدِّلات وتغيير أنماط الكتلة لوضع الكتلة على الصفحة ، عليك أن تفهم شيئًا واحدًا:المسافة البادئة من الكتلة الأصلية ليست ميزة للكتلة المتداخلة. إنها سمة من سمات الكتلة الأم. يجب أن تعلم أنه يجب وضع مسافة بادئة للكتلة المتداخلة من الحد بعدد معين من وحدات البكسل.
- استخدم مزيج. يتم تضمين المعلومات حول موضع الكتلة المتداخلة في عناصر الكتلة الأصلية. ثم يتم خلط عنصر الكتلة الأصل في الكتلة المتداخلة. في هذه الحالة ، لا تحدد الكتلة المتداخلة أي مسافات بادئة ويمكن إعادة استخدامها بسهولة في أي مكان.
دعنا نكمل بمثالنا:
<div> <ul class="menu header__menu"> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> <li class="menu__item"><a href=""></a></li> </ul> </div>
في هذه الحالة ، يتم تعيين الهندسة الخارجية وموضع كتلة menu
من خلال عنصر header__menu
. لا تحدد كتلة menu
أي مسافات بادئة ويمكن إعادة استخدامها بسهولة.
يؤدي عنصر الكتلة الأصل (في حالتنا هو header__menu
) مهمة كتل الغلاف المسؤولة عن تحديد الموضع الخارجي للكتلة.
كتل في هيكل الملف
جميع مشاريع BEM لها هيكل ملف مماثل. تسهل بنية الملف المألوفة على المطورين التنقل في المشروع والتبديل بين المشاريع ونقل الكتل من مشروع إلى آخر.
يتم تخزين تنفيذ كل كتلة في مجلد مشروع منفصل. كل تقنية (CSS ، JavaScript ، الاختبارات ، القوالب ، الوثائق ، الصور) موجودة في ملف منفصل.
على سبيل المثال ، إذا تم تعيين مظهر كتلة input
باستخدام CSS ، فسيتم حفظ الكود في ملف input.css
.
project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript
يتم أيضًا تخزين رمز المُعدِّلات والعناصر في ملفات منفصلة للكتلة. يسمح لك هذا الأسلوب بتضمين المُعدِّلات والعناصر الضرورية في الإنشاء فقط لتنفيذ الكتلة.
project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript input_theme_sun.css # The "input_theme_sun" modifier implementation input__clear.css # The "input__clear" element implementation with CSS input__clear.js # The "input__clear" element implementation with JavaScript
لتحسين التنقل في المشروع ، اجمع بين مُعدِّلات الكتلة مع قيم متعددة في الدلائل.
يتكون هيكل ملف أي مشروع BEM من مستويات إعادة التعريف (يمكنك معرفة المزيد عنها هنا). تسمح لك مستويات إعادة التعريف بما يلي:
- تقسيم المشروع إلى منصات ؛
- قم بتحديث مكتبات الكتل المضمنة في المشروع بسهولة ؛
- استخدام الكتل المشتركة لتطوير مشاريع متعددة ؛
- تغيير سمات التصميم دون التأثير على منطق المشروع ؛
- إجراء تجارب في مشروع حي.
استخدام الكتل وتخزين جميع تقنيات الكتلة في نفس المجلد يجعل من السهل نقل الكتل بين المشاريع. لنقل جميع أنماط وسلوك الكتلة مع التخطيط ، ما عليك سوى نسخ مجلد الكتلة إلى المشروع الجديد.
المزايا غير الواضحة للمنهجية
راحة التطوير الموازي
في BEM ، يتم تقسيم أي تخطيط إلى كتل. لأن الكتل مستقلة ، يمكن تطويرها بالتوازي من قبل العديد من المطورين.
ينشئ المطور كتلة كمكون عام يمكن إعادة استخدامه في أي مشروع آخر.
مثال على ذلك مكتبة كتلة مكونات bem ، والتي تحتوي على كتل عالمية ، مثل ارتباط ، زر ، وحقل إدخال. من الأسهل إنشاء كتل أكثر تعقيدًا من مكونات عالمية. على سبيل المثال ، محدد أو خانة اختيار.
يساعدك استخدام الكتل في تخطيط المشروع على توفير الوقت الذي تستغرقه في دمج التعليمات البرمجية التي كتبها العديد من المطورين ، ويضمن تفرد أسماء المكونات ، ويتيح لك اختبار الكتل في مرحلة التطوير.
اختبار التخطيط
من الصعب اختبار وظائف الصفحة بأكملها ، لا سيما في مشروع ديناميكي متصل بقاعدة بيانات.
في BEM ، يتم تغطية كل كتلة بالاختبارات. الاختبارات عبارة عن تقنية تنفيذ كتلة ، مثل Javascript أو CSS. يتم اختبار الكتل في مرحلة التطوير. من الأسهل التحقق من صحة كتلة واحدة ثم تجميع المشروع من الكتل المختبرة. بعد ذلك ، كل ما عليك فعله هو التأكد من أن غلاف الكتل يعمل بشكل صحيح.
بناء مشروع قابل للتخصيص
للتطوير المريح ، يتم وضع جميع الكتل والتقنيات في مشروع BEM في مجلدات وملفات منفصلة. لدمج ملفات المصدر في ملف واحد (على سبيل المثال ، لوضع جميع ملفات CSS في project.css
، وجميع ملفات JS في project.js
، وما إلى ذلك) ، نستخدم عملية الإنشاء.
يقوم الإصدار بتنفيذ المهام التالية:
- يجمع بين ملفات المصدر المنتشرة عبر نظام ملفات المشروع ؛
- يشمل فقط الكتل والعناصر والمعدلات الضرورية (كيانات BEM) في المشروع ؛
- يتبع ترتيب تضمين الكيانات ؛
- يعالج رمز الملف المصدر أثناء الإنشاء (على سبيل المثال ، يقوم بترجمة رمز LESS إلى كود CSS).
لتضمين كيانات BEM الضرورية فقط في البناء ، تحتاج إلى إنشاء قائمة من الكتل والعناصر والمعدلات المستخدمة في الصفحات. هذه القائمة تسمى إعلان .
نظرًا لأن كتل BEM تم تطويرها بشكل مستقل ووضعها في ملفات منفصلة في نظام الملفات ، فإنها لا تعرف أي شيء عن بعضها البعض. لبناء كتل على أساس الكتل الأخرى ، حدد التبعيات. هناك تقنية BEM مسؤولة عن هذا: ملفات deps.js
تتيح ملفات التبعية لمحرك الإنشاء معرفة الكتل الإضافية التي يجب تضمينها في المشروع.
حالة عملية: BEM ليس فقط لـ CSS
في الأقسام السابقة ، كل أمثلة الأكواد مخصصة لـ CSS. لكن BEM يسمح لك بتعديل سلوك الكتلة وتمثيلها في HTML بنفس الطريقة التعريفية كما في CSS.
كيفية استخدام القوالب في BEM
في HTML ، يتم تكرار ترميز الحظر في كل مرة يظهر فيها الحظر على الصفحة. إذا قمت بإنشاء ترميز HTML يدويًا ثم احتجت إلى إصلاح خطأ أو إجراء تغييرات ، فستحتاج إلى تعديل الترميز لكل مثيل من الكتلة. لإنشاء كود HTML وتطبيق الإصلاحات تلقائيًا ، يستخدم BEM القوالب ؛ الكتل مسؤولة عن طريقة تقديمها في HTML.
تسمح لك القوالب بما يلي:
- تقليل الوقت المستخدم لتصحيح أخطاء المشروع ، لأنه يتم تطبيق تغييرات القالب تلقائيًا على جميع كتل المشروع ؛
- تعديل تخطيط الكتلة ؛
- انقل الكتل بالتخطيط الحالي إلى مشروع آخر.
يستخدم BEM محرك قالب bem-xjst الذي يتميز بمحركين:
- BEMHTML
يحول وصف BEMJSON للصفحة إلى HTML. يتم وصف القوالب في ملفات .bemhtml.js. - بيمتري
يحول البيانات إلى BEMJSON. يتم وصف القوالب بتنسيق BEMJSON في ملفات .bemtree.js .
إذا لم تتم كتابة القوالب للكتل ، يقوم محرك القالب بتعيين علامة <div>
للكتل بشكل افتراضي.
قارن بين إعلان الكتل وإخراج HTML:
إعلان:
{ block: 'menu', content: [ { elem: 'item', content: { block: 'link'} }, { elem: 'item', elemMods: { current: true }, // Set the modifier for the menu item content: { block: 'link' } } ] }
لغة البرمجة:
<div class="menu"> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </div>
لتعديل تخطيط كتلة menu
، تحتاج إلى كتابة قوالب للكتلة:
- دعنا نغير علامة كتلة
menu
:block('menu')( tag()('menu') // Set the "menu" tag for the menu block )
HTML معدل:<menu class="menu"> <!-- Replace the "div" tag with the "menu" tag for the "menu" block --> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </menu>
على غرار CSS ، يتم تطبيق النموذج على جميع مجموعات "القائمة" في الصفحة. - أضف عنصرًا إضافيًا (
menu__inner
) يعمل كغلاف داخلي ويكون مسؤولاً عن تخطيط العناصر في كتلةmenu
. في الأصل لم يتم تضمين عنصرmenu__inner
في الإعلان ، لذلك يتعين علينا إضافته عند إنشاء القوالب.
تتم كتابة قوالب BEM بلغة JavaScript ، لذا يمكنك أيضًا استخدام JavaScript لإضافة عنصر جديد إلى القالب:block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content }; }) )
<menu class="menu"> <!-- Replace the "div" tag with the "menu" tag for the "menu" block --> <div class="menu__inner"> <div class="menu__item"> <div class="link"></div> </div> <div class="menu__item menu__item_current"> <div class="link"></div> </div> </div> </menu>
- استبدل العلامات لجميع
item
inner
والعناصر:block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content } }), elem('inner')( tag()('ul') ), elem('item')( tag()('li') ) )
<menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <div class="link"></div> </li> <li class="menu__item menu__item_current"> <div class="link"></div> </li> </ul> </menu>
- قم بتعيين علامة
<a>
لجميع الروابط على الصفحة:block('menu')( tag()('menu'), content()(function() { return { elem: 'inner', content: this.ctx.content } }), elem('inner')( tag()('ul') ), elem('item')( tag()('li') ) ); block('link')( tag()('a') );
<menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <a class="link"></a> </li> <li class="menu__item menu__item_current"> <a class="link"></a> </li> </ul> </menu>
- قم بتعديل القالب الموجود. يتم تطبيق القواعد في القوالب بنفس الطريقة كما في CSS: القاعدة السفلية تلغي قاعدة أعلى. أضف قواعد جديدة إلى النموذج وغيّر علامة الرابط من
<a>
إلى<span>
:block('link')( tag()('a') ); block('link')( tag()('span') );
<menu class="menu"> <ul class="menu__inner"> <li class="menu__item"> <span class="link"></span> </li> <li class="menu__item menu__item_current"> <span class="link"></span> </li> </ul> </menu>
BEM هو نظام قابل للتخصيص
توفر لك منهجية BEM قواعد صارمة لإنشاء نظام في مشروعك. ولكن في الوقت نفسه ، يمكن تخصيص الكثير من قواعد BEM. تتيح لك منهجية BEM تغيير اصطلاح التسمية أو اختيار بنية الملف الأكثر ملاءمة أو إضافة أي تقنيات تريدها إلى الكتلة.
الآن يمكنك ضبط النظام وإنشاء بطلك الخارق لـ BEM!
كيفية الحصول على المزيد من BEM
لبدء تعلم مبادئ BEM ، قم بزيارة موقعنا على الإنترنت. إذا كانت لديك أي أسئلة تود طرحها على الفريق ، فقم بالانضمام إلى قناة Telegram الخاصة بنا أو افتح مناقشة في منتدى BEM الخاص بنا.