Yeni Başlayanlar İçin BEM: Neden BEM'e İhtiyacınız Var?

Yayınlanan: 2022-03-10
Hızlı özet ↬ CSS stilleri yalıtımı, BEM kullanımının en sık başlangıç ​​noktasıdır. Ama bu, BEM'in size verebileceği en az şey. BEM, projenize bir sistem yaklaşımı getirir ve onu karmaşadan korur.

BEM, kodunuzu ölçeklenebilir ve yeniden kullanılabilir hale getirerek üretkenliği artırır ve ekip çalışmasını kolaylaştırır. Ekibin tek üyesi olsanız bile BEM işinize yarayabilir. Yine de birçok geliştirici, BEM gibi bir sistem yaklaşımının projelerine ek sınırlar koyduğuna ve projenizi aşırı yüklü, hantal ve yavaş hale getirdiğine inanıyor.

BEM'in tüm ana yönlerini yoğun bir biçimde toplayacağız. Bu makale, sadece 20 dakikada BEM'in temel fikirlerini anlamanıza ve sistem yaklaşımının projeniz için zararlı olduğuna dair önyargıları reddetmenize yardımcı olur.

Big BEM, Metodoloji , Teknolojiler , Kitaplıklar ve Araçlardan oluşur. Bu makalede, çok sayıda geliştiricinin yoğun deneyimi olduğu ve herhangi bir projeye sistematik bir yaklaşım getirdiği için metodolojinin kendisi hakkında daha fazla konuşacağız.

Size bazı pratik BEM vakalarını göstermek için BEM teknolojilerine değineceğiz ve kütüphaneleri ve araçları tamamen atlayacağız.

Teoriden pratiğe:

  • Sınıflar Dışında Seçici Kullanmamamızın Temel Nedenleri
  • BEM'in Temelleri
    • Bloklar ve Elemanlar
    • Değiştiriciler ve Karışımlar
    • Dosya Yapısındaki Bloklar
  • Metodolojinin Açık Olmayan Avantajları
  • Pratik Durum: BEM Sadece CSS İçin Değildir
  • BEM Özelleştirilebilir Bir Sistemdir

Peki, BEM bir kahraman mı yoksa bir kötü adam mı? O size kalmış! Ama önce makaleyi okuyun.

Batman logosu olarak BEM
BEMBatman
Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Sınıflar Dışında Seçici Kullanmamamızın Temel Nedenleri

BEM metodolojisinin temel kurallarından biri sadece sınıf seçicileri kullanmaktır. Bu bölümde nedenini açıklayacağız.

  • Neden kimlik kullanmıyoruz?
  • Neden etiket seçiciler kullanmıyoruz?
  • Neden evrensel bir seçici kullanmıyoruz?
  • Neden CSS sıfırlama kullanmıyoruz?
  • Neden iç içe seçiciler kullanmıyoruz?
  • Neden bir seçicide bir etiketi ve bir sınıfı birleştirmiyoruz?
  • Neden birleşik seçiciler kullanmıyoruz-
  • Neden nitelik seçicileri kullanmıyoruz?

Kimlik Kullanmıyoruz (Kimlik Seçiciler)

Kimlik, bir HTML öğesi için benzersiz bir ad sağlar. Ad benzersizse, onu arayüzde yeniden kullanamazsınız. Bu, kodu yeniden kullanmanızı engeller.

Yaygın yanlış anlamalar

  1. JavaScript'i kullanmak için kimlikler gereklidir.
    Modern tarayıcılar, kimlikler veya sınıflarla çalışabilir. Herhangi bir seçici türü tarayıcıda aynı oranda işlenir.
  2. Kimlikler <label> etiketi ile kullanılır.
    <label> bir denetimin içine yerleştirirseniz, bir kimliğe ihtiyaç duymaz. <input id="ID"><label for="ID">Text</label> yerine, sadece <label><input type="...">Text</label> kullanın.

Etiket Seçiciler Kullanmıyoruz

HTML sayfa işaretlemesi sabit değil: Yeni bir tasarım, bölümlerin iç içe yerleşimini, başlık düzeylerini (örneğin, <h1> 'den <h3> 'e) değiştirebilir veya <p> paragrafını <div> etiketine dönüştürebilir. Bu değişikliklerden herhangi biri, etiketler için yazılmış stilleri bozacaktır. Tasarım değişmese bile etiket kümesi sınırlıdır. Mevcut bir düzeni başka bir projede kullanmak için aynı etiketler için yazılmış stiller arasındaki çakışmaları çözmeniz gerekir.

Genişletilmiş bir semantik etiket seti de tüm yerleşim ihtiyaçlarını karşılayamaz.

Bir örnek, sayfa başlığının bir logo içermesidir. Logoya tıklandığında sitenin ana sayfası açılır ( index ). Resim için <img> etiketini ve bağlantı için <a> etiketini kullanarak etiketlerle işaretleyebilirsiniz.

 <header> <a href="/"> <img src="img.logo.png" alt="Logo"> </a> </header>

Metindeki logo bağlantısı ile sıradan bir bağlantı arasında ayrım yapmak için ekstra stillere ihtiyacınız var. Şimdi logo bağlantısından alt çizgiyi ve mavi rengi kaldırın:

 header a { ... }

Logo bağlantısının ana sayfada gösterilmesi gerekmez, bu nedenle dizin sayfası işaretlemesini değiştirin:

 <header> <!-- the <a> tag is replaced with <span> --> <span> <img src="img.logo.png" alt="Logo"> </span> </header>

<span> etiketi için alt çizgiyi ve mavi rengi kaldırmanız gerekmez. O halde farklı sayfalardan logo bağlantısı için genel kurallar koyalım:

 header a, header span { ... }

İlk bakışta, bu kod doğru görünüyor, ancak tasarımcının logoyu mizanpajdan kaldırdığını hayal edin. Seçici adları, logolu projeden hangi stillerin kaldırılması gerektiğini anlamanıza yardımcı olmaz. “A başlığı” seçicisi, bağlantı ile logo arasındaki bağlantıyı göstermez. Bu seçici, başlık menüsündeki bağlantıya veya örneğin yazarın profiline giden bağlantıya ait olabilir. "Başlık aralığı" seçicisi, başlığın herhangi bir bölümüne ait olabilir.

Karışıklığı önlemek için logo stillerini yazmak için logo sınıfı seçiciyi kullanın:

 .logo { ... }

CSS Sıfırlama Kullanmıyoruz

CSS sıfırlama, tüm sayfa için oluşturulmuş bir dizi global CSS kuralıdır. Bu stiller tüm düzen düğümlerini etkiler, bileşenlerin bağımsızlığını ihlal eder ve yeniden kullanılmasını zorlaştırır.

BEM'de “reset” ve “normalize” tek bir blok için bile kullanılmaz. Sıfırlama ve normalleştirme, mevcut stilleri iptal eder ve bunları daha sonra değiştirmeniz ve güncellemeniz gereken diğer stiller ile değiştirir. Sonuç olarak, geliştiricinin yeni sıfırlananları geçersiz kılan stiller yazması gerekir.

Evrensel Seçiciyi Kullanmıyoruz ( * )

Evrensel seçici, projenin düzendeki tüm düğümleri etkileyen bir stile sahip olduğunu belirtir. Bu, yerleşimin diğer projelerde yeniden kullanımını sınırlar:

  • Ayrıca yıldız işaretli stilleri projeye aktarmanız gerekir. Ancak bu durumda evrensel seçici, yeni projedeki stilleri etkileyebilir.
  • Yıldızlı stiller, aktardığınız düzene eklenmelidir.

Ayrıca evrensel bir seçici, proje kodunu tahmin edilemez hale getirebilir. Örneğin, evrensel kitaplık bileşenlerinin stillerini etkileyebilir.

Ortak stiller size zaman kazandırmaz. Geliştiriciler genellikle bileşenlerin tüm kenar boşluklarını sıfırlayarak başlar ( * { margin: 0; padding: 0; } ), ancak daha sonra bunları düzendekiyle aynı şekilde ayarlarlar (örneğin, margin: 12px; padding: 30px; ).

İç İçe Seçiciler Kullanmıyoruz

İç içe seçiciler kod birleştirmeyi artırır ve kodun yeniden kullanılmasını zorlaştırır.

BEM metodolojisi iç içe seçicileri yasaklamaz, ancak bunların çok fazla kullanılmamasını önerir. Örneğin, bloğun durumuna veya atanan temasına bağlı olarak öğelerin stillerini değiştirmeniz gerekiyorsa yuvalama uygundur.

 .button_hovered .button__text { text-decoration: underline; } .button_theme_islands .button__text { line-height: 1.5; }

Birleşik Seçiciler Kullanmıyoruz

Birleşik seçiciler, tekli seçicilerden daha spesifiktir ve bu da blokları yeniden tanımlamayı daha zor hale getirir.

Aşağıdaki kodu göz önünde bulundurun:

 <button class="button button_theme_islands">...</button>

Diyelim ki daha az yazma yapmak için .button.button_theme_islands seçicisinde CSS kuralları ayarladınız. Ardından bloğa “etkin” değiştiriciyi eklersiniz:

 <button class="button button_theme_islands button_active">...</button>

.button_active seçici, .button.button_theme_islands olarak yazılan blok özelliklerini yeniden tanımlamaz çünkü .button.button_theme_islands .button.button_theme_islands .button_active daha spesifiktir. Bunu yeniden tanımlamak için, blok değiştirici seçiciyi .button seçiciyle birleştirin ve .button.button_theme_islands altında bildirin çünkü her iki seçici de eşit derecede spesifiktir:

 .button.button_theme_islands {} .button.button_active {}

Basit sınıf seçiciler kullanırsanız, stilleri yeniden tanımlamada sorun yaşamayacaksınız:

 .button_theme_islands {} .button_active {} .button {}

Bir Seçicide Bir Etiket ve Bir Sınıfı Birleştirmiyoruz

Bir etiketi ve bir sınıfı aynı seçicide birleştirmek (örneğin, button.button ) CSS kurallarını daha belirgin hale getirir, dolayısıyla onları yeniden tanımlamak daha zordur.

Aşağıdaki kodu göz önünde bulundurun:

 <button class="button">...</button>

button.button seçicisinde CSS kurallarını belirlediğinizi varsayalım. Ardından active değiştiriciyi bloğa eklersiniz:

 <button class="button button_active">...</button>

.button_active seçici, button.button olarak yazılan blok özelliklerini yeniden tanımlamaz çünkü button.button .button_active button.button daha spesifiktir. Daha spesifik hale getirmek için blok değiştirici seçiciyi button.button_active etiketiyle birleştirmelisiniz.

Proje geliştikçe, input.button , span.button veya a.button seçicileri olan bloklar elde edebilirsiniz. Bu durumda, button bloğunun tüm değiştiricileri ve tüm iç içe öğeleri, her örnek için dört farklı bildirim gerektirecektir.

Olası İstisnalar

Nadir durumlarda, metodoloji etiket ve sınıf seçicilerin birleştirilmesine izin verir. Örneğin bu, doğru düzeni oluşturamayan CMS sistemlerinde yorum stilini ayarlamak için kullanılabilir.

Yorumu metin yazmak, resim eklemek veya işaretleme eklemek için kullanabilirsiniz. Bunları site tasarımıyla eşleştirmek için geliştirici, kullanıcıya sunulan tüm etiketler için stilleri önceden tanımlayabilir ve bunları iç içe bloklara kademelendirebilir:

 <div class="content"> ... <!-- the user's text --> </div> CSS rules: .content a { ... } .content p { font-family: Arial, sans-serif; text-align: center; }

Özellik Seçiciler Kullanmıyoruz

Nitelik seçiciler, sınıf seçicilerden daha az bilgilendiricidir. Kanıt olarak, başlıkta bir arama formu olan bir örnek düşünün:

 <header> <form action="/"> <input name="s"> <input type="submit"> </form> </header>

Form stillerini yazmak için seçici niteliklerini kullanmayı deneyin:

 header input[type=submit], header input[type=checkbox] { width: auto; margin-right: 20px; } header input[type=checkbox] { margin: 0; }

Bu örnekte, stillerin arama formuna ait olduğunu seçici adından kesin olarak söyleyemezsiniz. Sınıfları kullanmak daha net hale getirir. Sınıflarda net bir şekilde yazmanızı engelleyen kısıtlamalar yoktur. Örneğin, şöyle yazabilirsiniz:

 .form .search { ... }

Artık kod daha az belirsizdir ve stillerin arama formuna ait olduğu açıktır.

Ancak iç içe seçiciler, CSS kurallarını daha belirgin hale getirir ve mizanpajı projeler arasında aktarmanızı engeller. Yuvalamadan kurtulmak için BEM ilkelerini kullanın.

Özet : class , projedeki her bileşenin stillerini ayırmanıza izin veren tek seçicidir; kodun okunabilirliğini artırın ve mizanpajın yeniden kullanımını sınırlamayın.

CSS stilleri yalıtımı, BEM yolculuğunun en sık başlangıç ​​noktasıdır. Ama bu, BEM'in size verebileceği en az şey. BEM'de izole edilmiş bağımsız bileşenlerin nasıl düzenlendiğini anlamak için temel kavramları, yani Blok, Eleman, Değiştirici ve Karıştırmayı öğrenmeniz gerekir. Bunu bir sonraki bölümde yapalım.

BEM'in Temelleri

  • Bloklar ve Elemanlar
  • Değiştiriciler ve Karışımlar
  • Dosya Yapısındaki Bloklar

Blok ve Elemanlar

BEM metodolojisi, CSS, Sass, HTML, JavaScript veya React gibi kullanılan teknolojilerden bağımsız olarak uygulanabilen bir dizi evrensel kuraldır.

BEM, aşağıdaki görevlerin çözülmesine yardımcı olur:

  • Düzeni yeniden kullanın;
  • Bir proje içinde mizanpaj parçalarını güvenli bir şekilde hareket ettirin;
  • Bitmiş düzeni projeler arasında taşıyın;
  • Kararlı, öngörülebilir ve net kod oluşturun;
  • Proje hata ayıklama süresini azaltın.

Bir BEM projesinde arayüz, elemanlar içerebilen bloklardan oluşur. Bloklar, sayfanın bağımsız bileşenleridir. Bir öğe bloğun dışında var olamaz, bu nedenle her öğenin yalnızca bir bloğa ait olabileceğini unutmayın.

BEM'deki ilk iki harf, B kilitleri ve Öğeler anlamına gelir. Blok adı her zaman benzersizdir. Öğeler için ad alanını ayarlar ve blok parçaları arasında görünür bir bağlantı sağlar. Blok adları, bileşenler arasındaki bağlantıyı göstermek ve mizanpaj aktarılırken bu bileşenlerin herhangi bir parçasını kaybetmemek için uzun ama nettir.

BEM adlandırmanın tam gücünü görmek için bu örneği bir formla düşünün. BEM metodolojisine göre form, form bloğu kullanılarak uygulanır. HTML'de blok adı, class özniteliğine dahil edilir:

 <form class="form" action="/">

Formun kendi başına bir anlam ifade etmeyen tüm bölümleri ( form bloğu) öğeleri olarak kabul edilir. Yani arama kutusu ( search ) ve düğme ( submit ) form bloğunun öğeleridir. Sınıflar ayrıca bir elemanın bloğa ait olduğunu gösterir:

 <form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

Bloğun adının, öğenin adından özel bir ayırıcıyla ayrıldığına dikkat edin. BEM klasik adlandırma şemasında, ayırıcı olarak iki alt çizgi kullanılır. Her şey ayırıcı olarak çalışabilir. Alternatif adlandırma kuralları vardır ve her geliştirici kendilerine uygun olanı seçer. Önemli olan, ayırıcıların, blokları öğelerden ve değiştiricilerden programlı olarak ayırmanıza izin vermesidir.

Seçici adları, formu başka bir projeye taşımak için tüm bileşenlerini kopyalamanız gerektiğini açıkça belirtir:

 .form__search {} .form__submit {}

Sınıf adları için blokları ve öğeleri kullanmak önemli bir sorunu çözer: İç içe seçicilerden kurtulmamıza yardımcı olur. Bir BEM projesindeki tüm seçiciler aynı ağırlığa sahiptir. Bu, BEM'e göre yazılmış stilleri yeniden tanımlamanın çok daha kolay olduğu anlamına gelir. Şimdi aynı formu başka bir projede kullanmak için düzenini ve stillerini kopyalayabilirsiniz.

BEM bileşenlerini adlandırma fikri, blok ve öğeleri arasındaki bağlantıyı açıkça tanımlayabilmenizdir.

Değiştiriciler ve Karışımlar

Resmi olarak " M ", Modifier anlamına gelir, ancak aynı zamanda BEM'de bir başka önemli kavramı da ima eder: "mix". Hem değiştiriciler hem de karışımlar bir blokta ve öğelerinde değişiklik yapar. Buna daha yakından bakalım.

değiştiriciler

Bir değiştirici, bir bloğun veya bir öğenin görünümünü, durumunu ve davranışını tanımlar. Değiştirici eklemek isteğe bağlıdır. Değiştiriciler, istediğiniz sayıda değiştirici kullanabileceğiniz için farklı blok özelliklerini birleştirmenize izin verir. Ancak bir bloğa veya elemana aynı değiştiricinin farklı değerleri atanamaz.

Değiştiricilerin nasıl çalıştığını keşfedelim.

Projenin yukarıdaki örnekte olduğu gibi aynı arama formuna ihtiyacı olduğunu hayal edin. Aynı işlevlere sahip olmalı, ancak farklı görünmelidir (örneğin, sayfanın üstbilgisindeki ve altbilgisindeki arama formları farklı olmalıdır). Formun görünümünü değiştirmek için yapabileceğiniz ilk şey, ek stiller yazmaktır:

 header .form {} footer .form {}

header .form seçici, form seçiciden daha fazla ağırlığa sahiptir; bu, bir kuralın diğerini geçersiz kılacağı anlamına gelir. Ancak tartıştığımız gibi, iç içe seçiciler kod birleştirmeyi artırır ve yeniden kullanımı zorlaştırır, bu nedenle bu yaklaşım bizim için çalışmaz.

BEM'de, bloğa yeni stiller eklemek için bir değiştirici kullanabilirsiniz:

 <!-- 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> satırı, bloğa original değere sahip bir type değiştirici atandığını gösterir. Klasik bir şemada, değiştirici adı blok veya eleman adından bir alt çizgi ile ayrılır.

Formun benzersiz bir rengi, boyutu, türü veya tasarım teması olabilir. Tüm bu parametreler bir değiştirici ile ayarlanabilir:

 <form class="form form_type_original form_size_m form_theme_forest"> <form class="form form_type_original form_size_m form_theme_forest">

Aynı form farklı görünebilir ancak aynı boyutta kalabilir:

 <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>

Ancak her değiştirici için seçiciler yine aynı ağırlığa sahip olacaktır:

 .form_type_original {} .form_size_m {} .form_theme_forest {}

Önemli : Bir değiştirici, yalnızca orijinal blok uygulamasını bir şekilde değiştiren ek stiller içerir. Bu, evrensel bir bloğun görünümünü yalnızca bir kez ayarlamanıza ve değiştirici stillerine yalnızca orijinal blok kodundan farklı olan özellikleri eklemenize olanak tanır.

 .form { /* universal block styles */ } .form_type_original { /* added styles */ }

Bu nedenle bir değiştirici her zaman blok ve ilişkili olduğu öğeyle aynı DOM düğümünde olmalıdır.

 <form class="form form_type_original"></form>

Çok özel durumlarda evrensel bileşenleri uygulamak için değiştiricileri kullanabilirsiniz. Blok ve eleman kodu değişmez. DOM düğümünde gerekli değiştirici kombinasyonu oluşturulur.

karışımlar

Karıştırma, aynı biçimlendirmeyi farklı HTML öğelerine uygulamanıza ve kod tekrarından kaçınırken çeşitli varlıkların davranış ve stillerini birleştirmenize olanak tanır. Soyut sarmalayıcı blokları değiştirebilirler.

Karma, tek bir DOM düğümünde birkaç BEM varlığını (bloklar, öğeler, değiştiriciler) barındırdığınız anlamına gelir. Değiştiricilere benzer şekilde, blokları değiştirmek için karışımlar kullanılır. Bir karışımı ne zaman kullanmanız gerektiğine dair bazı örneklere bakalım.

Bloklar sadece görsel olarak değil, aynı zamanda anlamsal olarak da farklılık gösterebilir. Örneğin, bir arama formu, bir kayıt formu ve pasta sipariş formu tüm formlardır. Mizanpajda “form” bloğu ile uygulanırlar ancak ortak stilleri yoktur. Bu tür farklılıkları bir değiştirici ile ele almak imkansızdır. Bu tür bloklar için ortak stiller tanımlayabilirsiniz ancak kodu yeniden kullanamazsınız.

 .form, .search, .register { ... }

Aynı form için anlamsal olarak farklı bloklar oluşturmak için bir karışım kullanabilirsiniz:

 <form class="form" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

.form sınıf seçicisi, herhangi bir forma (sipariş, arama veya kayıt) uygulanabilecek tüm stilleri açıklar:

 .form {}

Artık evrensel formdan bir arama formu oluşturabilirsiniz. Bunu yapmak için projede ek bir search sınıfı oluşturun. Bu sınıf sadece aramadan sorumlu olacaktır. .form ve .search sınıflarının stillerini ve davranışını birleştirmek için bu sınıfları tek bir DOM düğümüne yerleştirin:

 <form class="form search" action="/"> <input class="form__search" name="s"> <input class="form__submit" type="submit"> </form>

Bu durumda, .search sınıfı, davranışı tanımlayan ayrı bir bloktur. Bu blok, form, temalar ve boyutlardan sorumlu değiştiricilere sahip olamaz. Bu değiştiriciler zaten evrensel forma aittir. Bir karışım, bu blokların stillerini ve davranışlarını birleştirmeye yardımcı olur.

Bileşenin semantiğinin değiştirildiği bir örnek daha alalım. Tüm girişlerin bağlantı olduğu sayfa başlığında bir gezinme menüsü:

 <nav class="menu"> <a class="link" href=""></a> <a class="link" href=""></a> <a class="link" href=""></a> </nav>

Bağlantı işlevi, link bloğunda zaten uygulanmaktadır, ancak menü bağlantılarının metindeki bağlantılardan görsel olarak farklı olması gerekir. Menü bağlantılarını değiştirmenin birkaç yolu vardır:

  1. Girişi bir bağlantıya dönüştüren bir menü girişi değiştiricisi oluşturun:
     <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>

    Bu durumda, değiştiriciyi uygulamak için "bağ" blok davranışını ve stillerini kopyalamanız gerekir. Bu, kod çoğaltmasına yol açacaktır.
  2. "link" evrensel bloğu ile "menü" bloğunun "item" öğesinin bir karışımını kullanın:
     <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>

    İki BEM öğesinin karışımıyla, artık "bağ" bloğundan temel bağlantı işlevselliğini ve "menü" bloğundan ek CSS kurallarını uygulayabilir ve kod tekrarını önleyebilirsiniz.

Dış Geometri ve Konumlandırma: Soyut HTML Sarmalayıcılarından Vazgeçmek

Karışımlar, bir bloğu diğer bloklara göre konumlandırmak veya öğeleri bir blok içinde konumlandırmak için kullanılır. BEM'de geometri ve konumlandırmadan sorumlu stiller üst blokta ayarlanır. Başlığa yerleştirilmesi gereken evrensel bir menü bloğunu ele alalım. Düzende, bloğun üst bloktan 20 piksel girintisi olmalıdır.

Bu görevin birkaç çözümü var:

  1. Menü bloğu için girintili stiller yazın:
     .menu { margin-left: 20px; }

    Bu durumda, "menü" bloğu artık evrensel değildir. Menüyü sayfa altbilgisine yerleştirmeniz gerekiyorsa, girintiler muhtemelen farklı olacağından stilleri düzenlemeniz gerekecektir.
  2. Menü bloğu değiştiricisini oluşturun:
     <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; }

    Bu durumda proje iki tür menü içerecektir, ancak durum böyle değildir. Menü aynı kalır.
  3. Bloğun harici konumunu tanımlayın: "menü" bloğunu soyut sarmalayıcıya yerleştirin (örneğin, "sarma" bloğu) tüm girintileri ayarlayın:
     <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>

    Değiştiriciler oluşturma ve bloğu sayfada konumlandırmak için blok stillerini değiştirme cazibesinden kaçınmak için bir şeyi anlamanız gerekir:

    Bir üst bloğun girintisi, iç içe bloğun bir özelliği değildir. Bu, ana bloğun bir özelliğidir. Yuvalanmış bloğun kenarlıktan belirli sayıda piksel ile girintilenmesi gerektiğini bilmesi gerekir.
  4. Bir karışım kullanın. Yuvalanmış blok konumlandırma hakkındaki bilgiler, ana blok öğelerine dahil edilir. Ardından ana blok öğesi, iç içe bloğa karıştırılır. Bu durumda, iç içe blok herhangi bir girinti belirtmez ve herhangi bir yerde kolayca yeniden kullanılabilir.

Örneğimizle devam edelim:

 <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>

Bu durumda, menu bloğunun dış geometrisi ve konumu, header__menu öğesi aracılığıyla ayarlanır. menu bloğu herhangi bir girinti belirtmez ve kolayca yeniden kullanılabilir.

Ana blok elemanı (bizim durumumuzda bu header__menu ), bloğun harici olarak konumlandırılmasından sorumlu olan sarmalayıcı blokların görevini yerine getirir.

Dosya Yapısındaki Bloklar

Tüm BEM projeleri benzer bir dosya yapısına sahiptir. Tanıdık dosya yapısı, geliştiricilerin projede gezinmesini, projeler arasında geçiş yapmasını ve blokları bir projeden diğerine taşımasını kolaylaştırır.

Her bloğun uygulaması ayrı bir proje klasöründe saklanır. Her teknoloji (CSS, JavaScript, testler, şablonlar, belgeler, resimler) ayrı bir dosyadadır.

Örneğin, input bloğu görünümü CSS ile ayarlanmışsa, kod input.css dosyasına kaydedilir.

 project common.blocks/ input/ input.css # The "input" block implementation with CSS input.js # The "input" block implementation with JavaScript

Değiştiriciler ve öğeler için kod da bloğun ayrı dosyalarında saklanır. Bu yaklaşım, yapıya yalnızca bloğun uygulanması için gerekli olan değiştiricileri ve öğeleri dahil etmenize izin verir.

 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

Proje gezinmesini iyileştirmek için, dizinlerdeki birden çok değerle blok değiştiricileri birleştirin.

Herhangi bir BEM projesinin dosya yapısı, yeniden tanımlama düzeylerinden oluşur (bunlarla ilgili daha fazla bilgiyi buradan edinebilirsiniz). Yeniden tanımlama seviyeleri şunları yapmanızı sağlar:

  • Projeyi platformlara ayırın;
  • Projeye dahil olan blok kitaplıklarını kolayca güncelleyin;
  • Birden fazla proje geliştirmek için ortak blokları kullanın;
  • Proje mantığını etkilemeden tasarım temalarını değiştirin;
  • Canlı bir projede deneyler yapın.

Blokları kullanmak ve tüm blok teknolojilerini aynı klasörde depolamak, blokları projeler arasında taşımayı kolaylaştırır. Bloğun tüm stillerini ve davranışını düzen ile birlikte taşımak için blok klasörünü yeni projeye kopyalamanız yeterlidir.

Metodolojinin Açık Olmayan Avantajları

Paralel Geliştirmenin Kolaylığı

BEM'de herhangi bir düzen bloklara bölünmüştür. Bloklar bağımsız olduğundan, birkaç geliştirici tarafından paralel olarak geliştirilebilirler.

Bir geliştirici, başka herhangi bir projede yeniden kullanılabilecek evrensel bir bileşen olarak bir blok oluşturur.

Bir örnek, bağlantı, düğme ve giriş alanı gibi evrensel bloklar içeren bem-bileşenleri blok kitaplığıdır. Evrensel bileşenlerden daha karmaşık bloklar oluşturmak daha kolaydır. Örneğin, bir seçici veya onay kutusu.

Proje düzeninde blokları kullanmak, birkaç geliştirici tarafından yazılan kodu entegre ederken zamandan tasarruf etmenize yardımcı olur, bileşen adlarının benzersizliğini garanti eder ve geliştirme aşamasında blokları test etmenize olanak tanır.

Düzeni Test Etme

Özellikle bir veritabanına bağlı dinamik bir projede, tüm sayfanın işlevselliğini test etmek sorunludur.

BEM'de her blok testler kapsamındadır. Testler, Javascript veya CSS gibi bir blok uygulama teknolojisidir. Bloklar geliştirme aşamasında test edilir. Bir bloğun doğruluğunu kontrol etmek ve ardından projeyi test edilmiş bloklardan birleştirmek daha kolaydır. Bundan sonra yapmanız gereken tek şey blok sarmalayıcının doğru çalıştığından emin olmaktır.

Bir Projenin Özelleştirilebilir Yapısı

Uygun geliştirme için, bir BEM projesindeki tüm bloklar ve teknolojiler ayrı klasörlere ve dosyalara yerleştirilir. Kaynak dosyaları tek bir dosyada birleştirmek için (örneğin, tüm CSS dosyalarını project.css içine, tüm JS dosyalarını project.js içine vb. koymak için), oluşturma işlemini kullanırız.

Yapı aşağıdaki görevleri gerçekleştirir:

  • Projenin dosya sistemine yayılmış kaynak dosyalarını birleştirir;
  • Projede yalnızca gerekli blokları, öğeleri ve değiştiricileri (BEM varlıkları) içerir;
  • Varlıkları dahil etme sırasını takip eder;
  • Derleme sırasında kaynak dosya kodunu işler (örn. DAHA AZ kodu CSS koduna derler).

Yapıya yalnızca gerekli BEM varlıklarını dahil etmek için, sayfalarda kullanılan blokların, öğelerin ve değiştiricilerin bir listesini oluşturmanız gerekir. Bu listeye deklarasyon denir.

BEM blokları bağımsız olarak geliştirildiğinden ve dosya sisteminde ayrı dosyalara yerleştirildiğinden, birbirleri hakkında hiçbir şey 'bilmezler'. Diğer bloklara dayalı bloklar oluşturmak için bağımlılıkları belirtin. Bundan sorumlu bir BEM teknolojisi var: deps.js dosyaları. Bağımlılık dosyaları, yapı motorunun projeye hangi ek blokların dahil edilmesi gerektiğini bilmesini sağlar.

Pratik Durum: BEM Sadece CSS İçin Değildir

Önceki bölümlerde, tüm kod örnekleri CSS içindir. Ancak BEM, bloğun davranışını ve HTML'deki temsilini CSS'dekiyle aynı bildirimsel yolla değiştirmenize izin verir.

BEM'de Şablonlama Nasıl Kullanılır

HTML'de blok işaretleme, blok sayfada her göründüğünde tekrarlanır. HTML işaretlemesini manuel olarak oluşturursanız ve ardından bir hatayı düzeltmeniz veya değişiklik yapmanız gerekirse, bloğun her örneği için işaretlemeyi değiştirmeniz gerekecektir. HTML kodu oluşturmak ve düzeltmeleri otomatik olarak uygulamak için BEM şablonları kullanır; bloklar, HTML'de sunulma biçiminden sorumludur.

Şablonlar şunları yapmanızı sağlar:

  • Şablon değişiklikleri tüm proje bloklarına otomatik olarak uygulandığından, proje hata ayıklaması için kullanılan süreyi azaltın;
  • Blok düzenini değiştirin;
  • Mevcut yerleşime sahip blokları başka bir projeye taşıyın.

BEM, iki motor içeren bem-xjst şablon motorunu kullanır:

  • BEMHTML
    Sayfanın BEMJSON açıklamasını HTML'ye dönüştürür. Şablonlar .bemhtml.js dosyalarında açıklanmıştır.
  • BEMTREE
    Verileri BEMJSON'a dönüştürür. Şablonlar, .bemtree.js dosyalarında BEMJSON formatında açıklanmıştır.

Bloklar için şablonlar yazılmamışsa, şablon motoru varsayılan olarak bloklar için <div> etiketini ayarlar.

Blokların bildirimini ve HTML çıktısını karşılaştırın:

Beyanname:

 { block: 'menu', content: [ { elem: 'item', content: { block: 'link'} }, { elem: 'item', elemMods: { current: true }, // Set the modifier for the menu item content: { block: 'link' } } ] }

HTML:

 <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 bloğu düzenini değiştirmek için, blok için şablonlar yazmanız gerekir:

  1. menu bloğu etiketini değiştirelim:
     block('menu')( tag()('menu') // Set the "menu" tag for the menu block )

    Değiştirilmiş 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'ye benzer şekilde, şablon sayfadaki tüm "menü" bloklarına uygulanır.
  2. İç sarmalayıcı olarak çalışan ve menu bloğundaki öğelerin düzeninden sorumlu olan fazladan bir öğe ( menu__inner ) ekleyin. Başlangıçta menu__inner öğesi bildirime dahil edilmedi, bu yüzden onu şablonlar oluşturulduğunda eklememiz gerekiyor.

    BEM şablonları JavaScript'te yazılmıştır, böylece şablona yeni bir öğe eklemek için JavaScript'i de kullanabilirsiniz:
     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>
  3. Tüm inner ve item öğeleri için etiketleri değiştirin:
     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>
  4. Sayfadaki tüm bağlantılar için <a> etiketini ayarlayın:
     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>
  5. Mevcut şablonu değiştirin. Şablonlardaki kurallar, CSS'dekiyle aynı şekilde uygulanır: daha düşük bir kural, daha yüksek bir kuralı geçersiz kılar. Şablona yeni kurallar ekleyin ve bağlantı etiketini <a> yerine <span> olarak değiştirin:
     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 Özelleştirilebilir Bir Sistemdir

BEM metodolojisi, projenizde bir sistem oluşturmanız için size katı kurallar sunar. Ancak aynı zamanda birçok BEM kuralı özelleştirilebilir. BEM metodolojisi, adlandırma kuralını değiştirmenize, en uygun dosya yapısını seçmenize veya bloğa istediğiniz herhangi bir teknolojiyi eklemenize olanak tanır.

Artık sistemi ayarlayabilir ve kendi BEM süper kahramanınızı yapabilirsiniz!

Kaptan Amerika logosu olarak BEM
BEM Kaptan Amerika

BEM'den Nasıl Daha Fazla Yararlanılır

BEM ilkelerini öğrenmeye başlamak için web sitemizi ziyaret edin. Ekibe sormak istediğiniz herhangi bir sorunuz varsa, Telegram kanalımıza katılın veya BEM Forumumuzda bir tartışma açın.