Web Geliştirme, css, bem, oocss, itcss
CSS Metodolojileri Hakkında Öğrendiklerim ve Görüşlerim
İlk CSS deneyimimi edinmeye çalıştığım zamanlarda, hayat iyi gidiyordu. Bir problemle karşılaştığımda noktalı virgül eksikliği gibi basit sözdizimi hatalarını farkeder düzeltir; zıkkım kutuyu ortalayamadığında Stack Overflow’a koşup kopyala-yapıştır yapıp çözer, kendiliğinden geliştirdiğiniz şeyi deneme yanılma tarayıcınızın Yenile tuşuna abanır, o şey bir şekilde çalıştığında mutlu olur, kodu rafa kaldırırdınız. Sonraki aşamalarda da hani insanın daha fazla şey isteme arzusu olur ya zaferin tadını aldığında? O vakit işler gittikçe boka sarıyor ve CSS’in karanlık tarafını görmeye başlıyorsunuz: Specificity Wars. Türkçesiyle, Özgüllük Savaşı. (Bu arada şimdiden belirteyim, elimden gelince plaza çalışanı olmamaya direnip terimleri Türkçe olarak bahsetmeye çalışacağım, saçma çeviriler için daha iyi fikri olan yazsın düzelteyeyim, Google Çeviri’nin yalancısıyım da.)
Özgüllük Savaşı
Kısaca bahsetmek gerekirse, (uzunu için buraya) elementlere, kutucuklara biçim atadığımızda bir seviyede özgüllüğe sahip olur. Siz bunu iyice abanarak hangi ebeveyne ait olduğundan tutun, elementin etiketini de dahil edip sınıf ismini süs gibi tutarsanız, kod genişledikçe yapmak istediğiniz tasarıma odaklanmaktan çok hangi biçimlendirmenin söz hakkına sahip olup olmadığını ayarlamaya çalışırsınız. Oysaki normalde, sadece istediğiniz bir biçimlendirmeyi istediğiniz bir elementin sadece sınıfına uygularsınız ve o biçim ona ait olur.
He diyelim ki bunları yok saydınız, illahaki bir noktada duvarlara tosluyorsunuz sonra onca yazdığınız şeyler işin içinden çıkılmaz hale geliyor. Bir elementin tanımı bir diğerinden üstün geliyor, hadi neyse deyip !important yapıştırıp günü kurtarıyorsunuz. Ama nereye kadar? Tabi ben bu işi yanlış yaptığımı anladığım an baya ara verip neyin yapılıp neyin yapılmaması gerektiğini araştırmaya koyuldum.
Metodolojiye Duyulan İhtiyaç
CSS’de oluşabilecek problemlerin bir sebebi serbest olması aslında. Bir şeyin tasarımını birçok farklı yollarla, istediğiniz şekilde tanımlayarak özgürlüğü tadabiliyorsunuz. Ama her zaman sırf bir seyi yapabiliyorsunuz diye onu yapmak zorunda değilsiniz. CSS, getirdiği özgürlükle beraber bize kendi kodumuzun sürdürebilirliğini, büyüyebilirliğini, modüler olmasını bize vazife olarak yüklüyor. Her acemi görünüşe göre o vazifeyi yerine getiremeyecek kadar daha sözdizimine, bir şeylerin nasıl çalıştığını anlamanın derdinde. İşte o acemilik aşamasından sonra daha da CSS’in üstüne gittiğinizde artık projenizin genişleyebilirliğini korumaya çalışabilmek için kendinizi bir takım disiplinlere sokacak metodolojilere bağlı oluyorsunuz.
Şu ana kadar öğrenmeye çalıştığım CSS metodolojileri (ve adlandırma kuralları), OOCSS (Obje Odaklı CSS), BEM (blok__element--modifiye
), BEVM (varyasyon/çeşit), aBEM (Atomik CSS değil); ve metotların yanında da dosya dizilimi olarak ITCSS (Ters üçgen CSS) ve Sass kılavuzlarında bahsedilen 7-1 modeli.
Her bulduğumu kullanıyor gibi görünebilirim ama elimden gelince tüm kaynakları anlamaya çalıştığımdan her birinin amacını, nasıl ayarlanacağını anlamaya çalışıyorum. Hem zaten bütün bu metodların birbirine %100 uyduğu söylenemez, zaten metodlar kronolojik sırayla listeleyerek az çok hepsinin bir öncesinden etkilenerek ortaya çıktığını kastediyorum. Üstelik önceki paragrafı okurken ilk düşündüğünüz gibi her bulduğunuzu kullanmayın, ölçüp tartın. Yoksa karmaşaya son vermek adına kullanacağınız metodolojilerden karmaşa yaratırsınız.
Obje Odaklı CSS
İlk olarak OOCSS’in sunumundan anladıklarımı aktarmak istiyorum. OOCSS, benim en geç dikkat ettiğim ama en ‘erkenden öğrenmeliymişim’ dedirten önemli bir takım kurallara sahip bir metodoloji. Tabi şu ana kadar en erken çözümlerden biri olması CSS’in en bariz problemlerini silip süpürecek büyük potansiyele sahip olduğunu gösteriyor. Hani metodolojilerden çekinen varsa en azından sadece OOCSS’e baksanız da yeter diyebilirim.
Obje odaklı CSS sunum sayfalarında bahsedilen en basit haliyle; stille temeli ve içerikle container’ı birbirinden ayırmayı hedefliyor. Oldukça basit ve mantıklı.
Yeniden kullanılabilirliği de esas almaya çalışıyor. Sunumdaki sayfaların birinde geçen örnekte Yahoo’nun finans sayfası çıkıyor. Birbirine oldukça benzeyen stiller bulunuyor ve OOCSS buna işaret ederek bundan kaçınmamızı istiyor. Çünkü bu zaten gereksiz. Yahoo’nun neden böyle bir şey yapmış olmasını sonradan eklemeli gereksiz stillendirmelere bağlayabiliriz bunu. (Gerçi sunumun yapıldığı zamanın Yahoo’sundan baya zaman geçmiştir, belki akıllanmışlardır.) Ama onun yerine elindeki biçimlendirmeleri değerlendirerek içeriğin türüne uygun koddan tasarruf ederek yeniden kullanılabilecek bir biçimlendirme uyguluyorsun.
Bunların dışında,
- Seçiciyi yazarken element+sınıf yerine sadece sınıf ismini tercih etmek.
- Genişliği ızgara (grid) kontrol eder, yüksekliği ise içerik.
maddelerine katılıyorum.
SMACSS Sıralaması
SMACSS’in açılımında da büyüyebilen ve modüler mimari tanımlanıyor. Tüm diğer metodolojiler gibi CSS’in genel problemlerini çözmekte. Ancak yeni gelen bir çok şey üzerine oldukça eskidiğini düşünüyorum (ya da önyargımdan dolayı dibine yeterince giremedim) ama hala bir takım şeylerin kullanmaya değer olduğunu bildiğim JavaScript durum sınıflandırılmaları ve stili okumayı, anlamayı kolaylaştıracak kendi nitelik sıralama düzeni var. (PostCSS eklentisi css-declaration-sorter paketi sağolsun, bazen bu düzeni düşünmeme gerek kalmıyor)
Blok Element Modifiye üçlüsü
İlk karşılaştığım ve böylece ilk defa CSS metotlarının olduğunu farkettiğim bir metot. BEM’in hem bir metodoloji hem de bir adlandırma kuralı olduğunu söyleyebiliriz.
İçeriğini, öğrendiğim sayfadan daha iyi hatırlayıp açıklayacağımı sanmıyorum, çevirileri şu şekilde:
Blok, diğerlerinden bağımsız, kendi başına anlamı olan bir varlık.
header, container, menu, checkbox, input
Element, kendi başına bir anlamı olmayan, herhangi bir bloğun parçası.
menu item, list item, checkbox caption, header title
Modifiye/niteleyici, blok ya da element üzerine koyulan bir bayrak. Görünümünü ya da davranışını değiştirmek için kullanın.
disabled, highlighted, checked, fixed, size big, color yellow
.header
.header__menu-item--color-yellow
.header__menu-item
gibi…
Sonralarında tepki olarak düzenlemeye giden bir başka adlandırma kuralları ortaya çıktı.
Blok Element Varyasyon Modifiye dörtlüsü
BEM’in düzenine göre bloklarınızı, elementlerinizi kurdunuz ve şimdi değişiklik yapmak istiyorsunuz diyelim. Değişiklik deyince aklımıza ilk modifiye gelmelidir ve temellere gerekmediğinde pek ellememek gerekir. Modifiye eklediğinizde bloğu ve elementi de tekrar yazmalısınız ki o modifiyenin neye ait olduğu bilinsin. CSS önişlemcileriyle zaten iç içe geçen tanımlarla yazım kolaylıkları sağlanıyor. Ama yine de çıktısında sürekli tekrar eden blok, element isimleriyle karşı karşıya kalıyorsunuz. Üstelik bütün bu metodolojilerin aslında büyük projeler için olduğunu düşünürsek gereksiz bayt birikimlerinin de çığ gibi büyümesi kaçınılmaz. İşte bunun için hem cüzi olsa da hız hem de okunabilirlik adına bir çözüm var.
BEVM’in sunumunda sınıf ismindeki modifiyenin varlığını yeniden değerlendiriyorlar ve ortaya varyasyon kısmı doğuyor. Etiketlerin nitelendirilmesinde çoklu ya da tek sınıflandırmalar arasındaki farka göre, tek sınıflandırmaya varyasyon, çoklu sınıflandırmalara modifiyelere yer veriyoruz.
Varyasyon bir elementin ya da bloğun değişik verisyonu, formu. Ve bunu yazarken blok__element blok__element--varyasyon
şeklinde değil, onun yerine geçecek şekilde yalnızca blok__element–varyasyon yazıyorsunuz. Çünkü burada mesele tekrarlanan isimleri en aza indirmek. Aza indirmek dedim, CSS tarafında eğer birde varyasyonu olmayan normal bir blok__element sınıfı olsaydı, diğer varyasyonla ortak olabilecek ifadeleri tekrar yazar ya da tehlikeli şeyler oluşturabilecek, yine önişlemcilerin ortaya çıkardığı @extend tanımını kullanırdınız.
/* Girdi (Herhangi bir önişlemci yardımıyla: postcss-extend, sass, less gibi...) */
.blok__element {
text-align: center;
}
.blok__element--farkli {
@extend .blok__element;
color: red;
}
/* Çıktı (CSS) */
.blok__element, .blok__element--farkli {
text-align: center;
}
.blok__element--farkli {
color: red;
}
Ama burada varyasyon tanımına yine dikkat çekmek gerek, modifiye kadar değişken ya da orijinaline yakın bir şey olmamalı. Böyle bir şey olmasın ki kullanmak zorunda olacağımız extend’in zararlarından kaçınmış olup BEVM’in faydalarından yararlanabilelim.
Modifiye isimlendirmeleri ise yine aynı ilk BEM örneklerinde gördüğümüz vazifeye sahip. Bulunduğu blok ya da elemente dekor, minik değişiklikler eklemek. Burda normal BEM’den farklı olarak ne tür bir modifiye olduğunu açıklayacak yazım kuralı oluyor (örn. renk-kırmızı, font-büyük…) ve modifiye için ayrı bir sınıf atıyorsunuz. BEVM’de bunu kullanmak için .blok__element--modifiye
yerine .blok__element.-modifiye
olarak kullanıyorsunuz. Eğer tanıdık geldiyse, komut bloğundaki araçları çalıştırırken bir ayar uyguladığınızda buna benzer sözdizimi olur:
vim --noplugin
<div class="kapı__kol -renk-altın"></div>
Bu modifiyelerin ayrı olarak kullanılmasının bir avantajı da dilediğiniz kadar zincirleme modifiye ekleyebiliyor olmanız.
<div class="... -metin-orta -font-büyük -renk-sarı -arkaplan-yeşil ..."></div>
Oldukça hoş gözüküyor.
aBEM ile daha kolay göz taraması
aBEM’in açılımı Atomik BEM şeklinde tabi bunun Atomik CSS tasarımıyla alakası yok sadece geliştirilmiş önekleri bunun tarzında. Öneklerse biyolojiden aklımızdan kalan atom, molekül, organizma. Ne olduğunu anlatmaya bile gerek yok. BEVM ve birazdan anlatacağım CSS mimarı Harry Roberts’ın açıklayıcı öneklerinden dolayı bir de bunun üstüne atomik isimlendirmelerin abartı olduğunu düşünüyorum. Genel özelliğini reddediyorum ama yazıda bulunmasının nedeni bu isimlendirmelerin dışında BEM’e olan antitezlerin bazılarının işime gelmesi.
Mesela camelCase davası. Sanki bunu sadece JavaScript’te yazmalısınız diye bir kanun var.
.ozel-bir-blok__uzun-bir-element-ismi--modifiye
.ozelBirBlok__uzunBirElementİsmi--modifiye
Hangisinin blok, element ve modifiye ismini daha iyi ayırt edebiliyorsunuz? Kolay olanı aBEM’in.
Harry Roberts’ın Katkıları
ITCSS
Özgüllük Savaşı’nı başlamadan bitirecek bir şey: Inverted Triangle CSS yani Ters Üçgen CSS metodolojisi.
Burada sınıf isimlendirmesi yerine projemizin dizinindeki isimlendirmelere yoğunlaşıyoruz.
- Ayarlar & Değişkenler: Evrensel değişkenler, konfigürasyonlar vb.
- Araçlar: Varsayılan mixin’ler, fonksiyonlar
- Genel: Stil sıfırlama dosyaları, box-sizing
- Elementler/Taban: Saf elementler, sınıflandırılmamış HTML elementleri
- Objeler: Görünüşten yoksun tasarım desenleri, OOCSS
- Bileşenler: Tasarlanmış bileşenler, UI yığınları
- Kozlar: Yardımcı araçlar, !important’lar
Bu listede alttan yukarıya giderseniz özgüllük azalıyor ve biçimlemelerin kapsamı artıyor. Ters yöne gidildiğinde özgüllük artıyor ve kapsam azalıyor. Burada neden ters üçgen dendiğini anlayabiliyorsunuzdur: kapsam gittikçe azalıyor yani üçgen aşağıya doğru sivriliyor.
İşin bir güzel yanı da bütün bu özgüllük, kapsam ve anlaşılırlık ilişkilerini ters üçgen şeklinin etrafında hayal ettiğiniz zaman daha akılda kalıcı oluyor.
Bunu nasıl dizine ayarlayabileceğimiz konusuysa aslında bize kalan durum. Metodolojinin sunumunda uygulanan ayarlamada, yukarıdaki maddelerin adında klasörler oluşturup içerisinde dilediğimiz kadar CSS/Sass dosyası ayırıp hepsini ana stil dosyasına @import aracılığıyla bağlanıyor. Zaten dizinler nasıl olursa olsun, ana fikir biçimlemelerin basamak basamak kapsamı azalacak, özgüllüğü artacak sırada olması.
Öneklerle daha şeffaf kullanıcı arayüzü
Harry Roberts’ın yazdığı makalede aslında sırf neden metodolojilere ihtiyacımın olduğunu açıklayarak başlıyor.
When we work at scale, we often find that we spend a large amount of our time reading, maintaining, and refactoring existing code, rather than writing and adding new features. This is the reason we focus so much on things like architectures, naming conventions, methodologies, preprocessors, scalability, etc.: because writing CSS is easy; looking after it is not.
Tabi metodların yanında kod yazarken self-documenting yani kendi kendine belgeleme alışkanlığını da yükseltecek şeyler gerekiyor. Bu role de sınıfların önüne gelecek önekler uyuyor. Bir sınıf içerisinde bloğun, elementin ve diğer ek tanımların bir arada yazarak az çok ne kastetmek istediğimizi belirtiyorduk. Burada ise direk sınıfın ne olduğunu, ne tür olduğunu yazarak gözümüzü eğitmiş olacağız.
Objelere o-, bileşenlere c- eki. Ve bununla beraber yardımcı olabilecek t-ema, s-cope, is-durumu, has-durumu, _important, diğer ekip üyelerinin işini kolaylaştıracak (benim açımdan pek umrumda değil ama vaktinde iş görecek) qa- js- ekleri olarak bulunuyor.
Aynı aBEM’deki atomik önekleri koymadan önce çekindiğim gibi bu makaledekilerden de çekingenliğim var. Ne de olsa sık sık uğraşıp bir noktada ezbere bileceğim sınıf isimleriyle yeri gelip ‘Ne gerek vardı ki bu gereksiz öneklere?’ Ama en azından aBEM’in aksine başka bir somutlaştırmaya ayak uydurmaktan çok, elime ilerisi için işi kolaylaştıracak, sınıfların ne olduğu tanımlayacak kısa bir şey vermesi beni bunu kullanmam için yeterince motive ediyor. Tabi denemeden de bilemem.
Tüm katkıların birleşimi BEMIT ve diğer ilaveler
BEM, ITCSS dizini ve önek kurallarından sonra tüm bunları birleştirerek Harry Roberts bir şekilde bunu BEMIT olarak adlandırmayı düşünmüş ve buna ilave olarak responsive eklerini, s-cope ekinin bir faydalı yönünü göstermiş.
.o-blok@laptop, .c-baskabirblok@telefon .o-blok@baski ...
Gördüğünüz üzere sınıfların sonuna @ ekini kullanarak farklı genişlikteki ekranlarda ne stillerin ekleneceğini HTML sayfasına bakarak anlayabiliyorsunuz. Kesin olarak ne yapmak istediğinizi de ayrı bir sınıfta bunu belirmiş oluyor, ne zaman isterseniz ayrı bir sınıf üzerinde kontrol altında tutabiliyorsunuz.
He bu arada kısa not: Bu sınıflandırmayı doğal olarak @media sorgusu içerisinde yapacağımız için,
@media print {
.o-blok\@baski {
display: none;
}
}
@ karakterinden önce () ters eğik çizgiyi eklemeyi unutmayalım ki CSS başka bir sorgu başlattığımızı düşünmesin.
7-1 Paterni
Hugo Giraudel’e ait Sass’ın prensiplerinin paylaşıldığı sitede bir şekilde rastgeldiğim 7-1 mimarisi vardı.
7 ayrı kategori tek ana stil dosyasına bağlı oluyor.
Dizin aşağıdaki gibi;
- Abstract: Değişkenler, ayarlamalar, mixin’ler
- Vendor: Dış kaynaklardan kullandığınız stiller. (Normalize.css, jQuery UI gibi)
- Genel: Sıfırlama, tipografi stilleri
- Bileşenler: Tuşlar, kapak bölümü, carousel vb.
- Düzen/Plan (Layout): Navigasyon, ızgara, header, footer…
- Sayfalar: Sayfaya özel olan stiller
- Temalar: Alternatif görünümlerin bulunduğu bölüm
Her ne kadar yazıda ITCSS’den bahsedilmese de listelerdeki kategorilerin içe aktarım sırası yine az çok ters üçgen tarzını anımsatıyor fakat farklı olarak biçimlemelerin özgüllüğüne göre ayrılan dosyaların dışında temalar, vendor ve layout kategorileri bulunmakta. Projede sorumlu olmadığınız dış kaynakları ayrı tutmak ve daha çok biçimlendirilecek alana odaklanabilmek için 7-1 paterni en uygun seçim.
Sentezim ne olacak?
Sonuç olarak az çok bu metodların sonlarına doğru açıkladığım kişisel görüşlerimin aracılığıyla bazı kuralları yoksayıp bazılarını sürdüreceğim elbet ama gerçekten bir sentezin çıkması, yapacağım projelerde edindiğim deneyimim belirleyecek. Belki hiç burda bahsedildiği kadar fazla metoda ihtiyacım olmayacak, belki açıkladıklarımdan çok başka bir metodla karşılaşacağım.
Nasıl olsa en başta bunu edinmek amacıyla, öğrendiklerimi pekiştirmek adına bu yazıyı hazırladım. Bir sonraki aşamanın zamanı gelecek. Geldiğinde buraya da gönderme yaparak ayrı bir yazı hazırlamayı düşünüyorum.
Sonuç
Bütün bu metodolojilerden sonra yapmayı planladığınız projeye başlamadan önce yalnızca tek merminiz var. Ya o kurallara göre gidilir ya da gidilmez. Sonucuna katlanmak zorunda kalırsınız. Yolun ortasında karar değiştirirseniz ve 600 satırlık kodun hepsine önek koymaya karar verirseniz, oldukça zaman kaybedersiniz. (Aklımdan geçmedi değil)
Bu yüzden tam projenin başlama noktasında iken ne planladıklarınızı iyi değerlendirip hangi kuralları uygulayacağınız tercihini ona göre vermelisiniz ki en başta hedeflediklerinizi sağlayabilesiniz.