BEM türleri
StyleSheet maker fonksiyonları, oluşturulan stilleri özel türler kullanarak tanımlayabilir; böylece bu fonksiyonlar kullanılırken TypeScript mevcut CSS seçicilerini önerir. Bu özellik, BEM metodolojisi ile TypeScript generics yapısını birleştirerek stil uygulama detaylarını harici bir arayüzün ardında gizler.
Belirli bir metodolojiye sıkı sıkıya bağlı kalmayan türlerin kullanılması önerilir. Daha fazla bilgi için CSS-in-TS bölümüne bakınız.
Stillerin tanımlanması
EffCSS kullanarak stiller geliştirmenin ilk adımı, sunulan işlevselliği BEM metodolojisinin üç seviyesindeki stillerinizi tanımlayan bir tür (type) olarak bildirmektir:
- bloklar (1. seviye),
- öğeler (2. seviye),
- değiştiriciler (3. seviye).
Tüm seviyeler için lowerCamelCase stilinde yazılmış anlamlı isimlerin kullanılması önerilir.
WARNING
İsimlerde nokta ve alt çizgi kullanmayın; çünkü bu karakterler EffCSS seçicilerini ve özniteliklerini oluşturmak için kullanılır.
INFO
Her üç seviyeyi de kullanmak zorunda değilsiniz. Stilleri BEM açısından tanımlamak istemiyorsanız seçicilerinizi tek tek bloklar düzeyinde tanımlamanız yeterlidir.
export type TCustomMaker = {
/**
* Default block
*/
'': {
/**
* Logo element
*/
logo: {
/**
* Spin animation
*/
spin: '';
/**
* Logo scale
*/
scale: 1 | 2;
};
/**
* Body element
*/
body: {
/**
* Padding size
*/
p: 's' | 'm' | 'l';
};
/**
* Footer element
*/
footer: {
/**
* Is footer hidden
*/
hidden: '';
};
};
/**
* Panel block
*/
panel: {
/**
* Default block
*/
'': {
/**
* Is panel modal
*/
modal: '';
/**
* Max panel width
*/
max: 'vw' | 'parent';
};
/**
* Close button block
*/
closeBtn: {};
}
};Blok, öğeler (elements) içermek zorunda değildir. Öğe de değiştiriciler (modifiers) içermek zorunda değildir.
Blok değiştiricilerinin, öğe içinde "" anahtarıyla 3. seviyede tanımlandığına dikkat edin. "" anahtarına sahip blok, varsayılan veya birincil blok olarak kabul edilir. Ayrıca, belirli bir bloğa ve/veya öğeye bağlı olmayan bazı yardımcı stillerin (utility sınıfları gibi) tanımlandığı durumlar da olabilir (örneğin Tailwind'deki gibi); işte bu noktada aşağıdaki açıklama devreye girer.
export type TCustomMaker = {
'': {
'': {
/**
* Width
*/
w: 's' | 'm' | 'l';
/**
* Height
*/
h: 's' | 'm' | 'l';
}
};
};Stillerin uygulanması
EffCSS kullanarak stil geliştirmenin ikinci adımı, tanımlanan işlevselliği StyleSheet maker fonksiyonu içinde hayata geçirmektir. EffCSSte BEM seçicileri oluşturmak için bem yardımcı aracı kullanılır. Genel (generic) bir yapıya sahip olan bu araç, aynı zamanda oluşturulan CSS seçicilerinin geçerliliğini de kontrol eder.
Her bir seçici; blok, öğe, değiştirici (modifier) ve (Boolean türünde değilse) değiştirici değeri isimlerinin bir nokta ile birleştirilmesiyle oluşturulur.
import { TStyleSheetMaker } from 'effcss';
export type TCustomMaker = {...};
const maker: TStyleSheetMaker = ({
bem,
}) => {
return {
// the default block selector
[bem<TCustomMaker>('')]: {...},
// selector for an element inside the default block
[bem<TCustomMaker>('.logo')]: {...},
// element boolean modifier selector
[bem<TCustomMaker>('.logo.spin')]: {}
// selector for a block modifier with a specific value
[bem<TCustomMaker>('panel..max.vw')]: {}
}
};
export default maker;Stillerin kullanımı
Hazır EffCSS stilleri, ilgili StyleSheet maker fonksiyonu Style provider nesnesinin use metoduna geçirilerek kullanılabilir. Kullanım şekli bem yardımcı aracına benzer; girilen argümanların TCustomMaker türüyle uyumluluğu da kontrol edilir.
import { IStyleProvider } from 'effcss';
import { default as customStyle, TCustomMaker } from './styles/custom';
const getStyle = (use: IStyleProvider['use']) => {
// EffCSS v3 returns a resolver function,
// and EffCSS v4 returns an array of resolvers
// you can also const [css] = use(customStyle);
return {
block: css<TCustomMaker>(''),
logo: css<TCustomMaker>('.logo'),
spinLogo: css<TCustomMaker>('.logo.spin'),
footer: css<TCustomMaker>('.footer'),
body: css<TCustomMaker>('.body.p.m'),
};
};Aynı anda birden fazla seçici oluşturmak için bir nesne de iletebilirsiniz.
import { IStyleProvider } from 'effcss';
import { default as customStyle, TCustomMaker } from './styles/custom';
const getStyle = (use: IStyleProvider['use']) => {
// EffCSS v3 returns a resolver function,
// and EffCSS v4 returns an array of resolvers
const [css] = use(customStyle);
return css<TCustomMaker>({
'': {
logo: {
spin: '',
scale: 2
};
}
});
};Ya da bir dize dizisi geçirebilirsiniz
import { IStyleProvider } from 'effcss';
import { default as customStyle, TCustomMaker } from './styles/custom';
const getStyle = (use: IStyleProvider['use']) => {
// EffCSS v3 returns a resolver function,
// and EffCSS v4 returns an array of resolvers
const [css] = use(customStyle);
return css<TCustomMaker>(['.logo.spin', '.logo.scale.2']);
};Alternatif olarak, önce MonoResolver nesnesini alıp ardından gerektiği şekilde hassaslaştırabilirsiniz.
import { IStyleProvider } from 'effcss';
import { default as customStyle, TCustomMaker } from './styles/custom';
const getStyle = (use: IStyleProvider['use']) => {
// EffCSS v3 returns a resolver function,
// and EffCSS v4 returns an array of resolvers
const [css] = use(customStyle);
const block = css<TCustomMaker>();
const logo = block.e('logo');
const logoSpin = logo.m({
spin: ''
});
return {
block: block.$,
logo: logo.$,
spinLogo: logoSpin.$,
footer: block.e('footer').$,
body: block.e('body').m({
p: 'm'
}).$,
};
};En çok hoşunuza giden yöntemi kullanın.
Öznitelik (attribute) oluşturma modları
Style provider bileşeni, iki öznitelik kullanarak BEM seçicilerinin oluşturulma şeklini etkileyebilir:
mode-a(data-*özniteliklerini kullanır) veyac(classözniteliğini kullanır) değerini alabilir,min- BEM seçicilerini küçültmenizi (minify) sağlayan bir Boolean özniteliğidir.
CSS sınıfı oluşturma yöntemi daha öngörülebilirdir; veri özniteliği (data attribute) oluşturma yöntemi ise farklı stil sayfalarını görsel olarak birbirinden ayırmanıza olanak tanır. Hangisi hoşunuza gidiyorsa onu kullanın.
Küçültme işlemi seçicide benzersiz bir öneki korur; böylece seçici uzunlukları önemli ölçüde azalırken farklı tabloların stilleri birbirinden izole kalmaya devam eder.
Avantaj
Açıklanan bu yaklaşım, sözleşmeyi (contract) uygulamadan (implementation) ayırmanıza olanak tanır. Geliştirme sürecinde hangi CSS seçicilerinin sağlanması gerektiğini baştan bilirsiniz; ayrıca herhangi bir üçüncü taraf geliştirici, StyleSheet maker fonksiyonunuzun içeriğini incelemeye gerek kalmadan TCustomMaker türünüzü içe aktarıp (import) gerekli stilleri elde edebilir. JS dosyalarının genellikle derleme sırasında küçültüldüğü göz önüne alındığında, önerilen bu yaklaşım ciddi oranda zaman tasarrufu sağlar.
Buna ek olarak, EffCSS her bir stil sayfası için kendine özgü BEM seçicileri oluşturur; bu da seçicilerin yeniden tanımlanması riskini ortadan kaldırır.
Böylece EffCSS, geleneksel CSS oluşturma yöntemlerinin ötesine geçmenizi sağlayarak CSS-in-TS yaklaşımına benzer bir yapı sunar.