BEM ve Modern CSS Seçiciler ile Aşamayı Dizginlemek PlatoBlockchain Veri Zekası. Dikey Arama. Ai.

BEM ve Modern CSS Seçicilerle Kaskadı Tam Hale Getirmek

BEM. Ön uç geliştirme dünyasındaki tüm teknikler gibi, BEM formatında CSS yazmak polarize olabilir. Ama bu – en azından benim Twitter balonumda – daha çok sevilen CSS metodolojilerinden biri.

Şahsen BEM'in iyi olduğunu düşünüyorum ve bence kullanmalısın. Ama aynı zamanda neden yapmayabileceğini de anlıyorum.

BEM hakkındaki görüşünüz ne olursa olsun, çeşitli avantajlar sunar, en önemlisi CSS Cascade'deki özgüllük çakışmalarını önlemeye yardımcı olmasıdır. Bunun nedeni, doğru kullanıldığında, BEM biçiminde yazılmış tüm seçicilerin aynı özgüllük puanına sahip olması gerektiğidir (0,1,0). Yıllar boyunca pek çok büyük ölçekli web sitesi için CSS tasarladım (devlet, üniversiteler ve bankaları düşünün) ve BEM'in gerçekten parladığını bu büyük projelerde buldum. Yazdığınız veya düzenlediğiniz stillerin sitenin başka bir bölümünü etkilemediğinden emin olduğunuzda, CSS yazmak çok daha eğlencelidir.

Spesifiklik eklemenin tamamen kabul edilebilir olduğu düşünülen istisnalar vardır. Örneğin: :hover ve :focus sözde sınıflar özgüllük puanına sahip olanlar 0,2,0. Bir diğeri ise sözde öğelerdir - benzeri ::before ve ::after - özgüllük puanına sahip olan 0,1,1. Yine de bu makalenin geri kalanında, başka herhangi bir özgüllük sürünmesi istemediğimizi varsayalım. 🤓

Ama gerçekten seni BEM'de satmak için burada değilim. Bunun yerine, onu modern CSS seçicilerle birlikte nasıl kullanabileceğimiz hakkında konuşmak istiyorum — düşünün :is(), :has(), :where(), vb. - eşit kazanmak için Daha kontrolü Çağlayan.

Modern CSS seçicilerle ilgili bu nedir?

The CSS Seçiciler Seviye 4 spesifikasyonu bize öğeleri seçmek için bazı güçlü yeni (ish) yollar sunar. Favorilerimden bazıları şunları içerir: :is(), :where(), ve :not(), her biri tüm modern tarayıcılar tarafından desteklenir ve günümüzde hemen hemen her projede güvenle kullanılabilir.

:is() ve :where() özgüllüğü nasıl etkiledikleri dışında temelde aynı şeydir. özellikle, :where() her zaman özgüllük puanına sahiptir 0,0,0. evet hatta :where(button#widget.some-class) özgüllüğü yoktur. Bu arada, özgüllük :is() bağımsız değişken listesindeki en yüksek özgüllüğe sahip öğedir. Dolayısıyla, halihazırda birlikte çalışabileceğimiz iki modern seçici arasında bir Cascade-wrangling ayrımına sahibiz.

inanılmaz derecede güçlü :has() ilişkisel sözde sınıf aynı zamanda hızla tarayıcı desteği kazanıyor (ve o zamandan beri CSS'nin en büyük yeni özelliğidir. Grid, Benim düşünceme göre). Ancak, bu yazıyı yazarken, tarayıcı desteği :has() henüz üretimde kullanım için yeterince iyi değil.

BEM'ime bu sözde sınıflardan birini yapıştırmama izin verin ve…

/* ❌ specificity score: 0,2,0 */
.something:not(.something--special) {
  /* styles for all somethings, except for the special somethings */
}

Hay aksi! Şu özgüllük puanını görüyor musunuz? Unutmayın, BEM ile ideal olarak seçicilerimizin hepsinin özgüllük puanına sahip olmasını istiyoruz. 0,1,0. Neden ki 0,2,0 kötü? Aynı örneği genişletilmiş olarak ele alalım:

.something:not(.something--special) {
  color: red;
}
.something--special {
  color: blue;
}

İkinci seçici kaynak sıralamasında sonuncu olmasına rağmen, birinci seçicinin daha yüksek özgüllüğü (0,2,0) kazanır ve rengi .something--special elemanlar ayarlanacak red. Yani, BEM'inizin düzgün yazıldığını ve seçilen öğenin hem .something temel sınıf ve .something--special HTML'de kendisine uygulanan değiştirici sınıf.

Dikkatsizce kullanılan bu sözde sınıflar, Cascade'i beklenmedik şekillerde etkileyebilir. Ve bu tür tutarsızlıklar, özellikle daha büyük ve daha karmaşık kod tabanlarında baş ağrısına neden olabilir.

Kahretsin. Şimdi ne olacak?

hakkında ne söylediğimi hatırla :where() ve özgüllüğünün sıfır olduğu gerçeği? Bunu lehimize kullanabiliriz:

/* ✅ specificity score: 0,1,0 */
.something:where(:not(.something--special)) {
  /* etc. */
}

Bu seçicinin ilk kısmı (.something) olağan özgüllük puanını alır 0,1,0. Ancak :where() - ve içindeki her şeyin - bir özelliği vardır 0, seçicinin özgüllüğünü daha fazla artırmaz.

:where() yuvalanmamızı sağlar

Spesifikliği benim kadar umursamayan insanlar (ve bu muhtemelen pek çok insan, adil olmak gerekirse), konu yuvalamaya geldiğinde oldukça iyiydi. Bazı kaygısız klavye vuruşlarıyla, şu şekilde bir CSS'ye sahip olabiliriz (kısalık için Sass kullandığımı unutmayın):

.card { ... }

.card--featured {
  /* etc. */  
  .card__title { ... }
  .card__title { ... }
}

.card__title { ... }
.card__img { ... }

Bu örnekte, elimizde bir .card bileşen. "Öne çıkan" bir kart olduğunda ( .card--featured sınıf), kartın başlığının ve görselinin farklı şekilde stilize edilmesi gerekir. Ama bizim gibi şimdi Biliyorsunuz, yukarıdaki kod, sistemimizin geri kalanıyla tutarsız olan bir özgüllük puanıyla sonuçlanıyor.

Ölümcül bir özgüllük ineği bunun yerine bunu yapmış olabilir:

.card { ... }
.card--featured { ... }
.card__title { ... }
.card__title--featured { ... }
.card__img { ... }
.card__img--featured { ... }

Bu o kadar da kötü değil, değil mi? Açıkçası, bu güzel bir CSS.

Yine de HTML'de bir dezavantaj var. Tecrübeli BEM yazarları, değiştirici sınıfları birden çok öğeye koşullu olarak uygulamak için gerekli olan hantal şablon mantığının muhtemelen acı verici bir şekilde farkındadır. Bu örnekte, HTML şablonunun koşullu olarak eklemesi gerekir. --featured üç öğeye değiştirici sınıf (.card, .card__title, ve .card__img) olsa da muhtemelen gerçek dünyadan bir örnekte daha da fazla. bu çok fazla if ifadeleri.

The :where() seçici, özgüllük düzeyine katkıda bulunmadan çok daha az şablon mantığı ve önyükleme için daha az BEM sınıfı yazmamıza yardımcı olabilir.

.card { ... }
.card--featured { ... }

.card__title { ... }
:where(.card--featured) .card__title { ... }

.card__img { ... }
:where(.card--featured) .card__img { ... }

İşte aynı şey ama Sass'ta (sondaki nota dikkat edin) işaretleri):

.card { ... }
.card--featured { ... }
.card__title { 
  /* etc. */ 
  :where(.card--featured) & { ... }
}
.card__img { 
  /* etc. */ 
  :where(.card--featured) & { ... }
}

Çeşitli alt öğelere değiştirici sınıflar uygulamak yerine bu yaklaşımı tercih edip etmemeniz kişisel tercih meselesidir. En azından :where() şimdi bize seçenek sunuyor!

BEM olmayan HTML ne olacak?

Mükemmel bir dünyada yaşamıyoruz. Bazen kontrolünüz dışında olan HTML ile uğraşmanız gerekir. Örneğin, biçimlendirmeniz gereken HTML'yi ekleyen bir üçüncü taraf komut dosyası. Bu biçimlendirme genellikle BEM sınıf adlarıyla yazılmaz. Bazı durumlarda bu stiller, kimlikler dışında sınıfları hiç kullanmaz!

Bir kez daha, :where() arkamız var Var olduğunu bildiğimiz DOM ağacının yukarısında bir yerde bir öğenin sınıfına başvurmamız gerektiğinden, bu çözüm biraz hileli.

/* ❌ specificity score: 1,0,0 */
#widget {
  /* etc. */
}

/* ✅ specificity score: 0,1,0 */
.page-wrapper :where(#widget) {
  /* etc. */
}

Yine de bir ana öğeye atıfta bulunmak biraz riskli ve kısıtlayıcı geliyor. Ya o ana sınıf değişirse ya da herhangi bir nedenle orada olmazsa? Daha iyi (ama belki de eşit derecede hileli) bir çözüm kullanmak olacaktır. :is() yerine. Unutma, özgüllük :is() seçici listesindeki en özel seçiciye eşittir.

Yani, var olduğunu bildiğimiz (veya umduğumuz!) bir sınıfa atıfta bulunmak yerine :where(), yukarıdaki örnekte olduğu gibi, oluşturulmuş bir sınıfa ve etiketi.

/* ✅ specificity score: 0,1,0 */
:is(.dummy-class, body) :where(#widget) {
  /* etc. */
}

Daima mevcut body seçmemize yardımcı olacak #widget unsurun varlığı ve .dummy-class aynı sınıf içinde :is() verir body seçici, bir sınıfla aynı özgüllük puanını (0,1,0)… ve kullanımı :where() seçicinin bundan daha spesifik olmamasını sağlar.

Bu kadar!

Modern özgüllük yönetimi özelliklerinden bu şekilde yararlanabiliriz. :is() ve :where() BEM biçiminde CSS yazarken elde ettiğimiz özgüllük çarpışma önlemesinin yanı sıra sözde sınıflar. Ve çok da uzak olmayan bir gelecekte, bir Zamanlar :has() Firefox desteği kazanır (şu anda yazım sırasında bir bayrağın arkasında desteklenmektedir), özgüllüğünü geri almak için muhtemelen onu :where() ile eşleştirmek isteyeceğiz.

BEM adlandırma konusunda her şeyi yapsanız da yapmasanız da, umarım seçici özgüllüğünde tutarlılığın iyi bir şey olduğu konusunda hemfikir olabiliriz!

Zaman Damgası:

Den fazla CSS Püf Noktaları