Skip to content

Kılavuz ​

CSS-Zero, sözleşme dosyalarına (.css.ts/.css.js) CSS stilleri yazmanıza olanak tanır. derleme zamanında derleyici bu dosyaları çalıştırır, her yardımcı program çağrısını deterministik bir dize jetonuyla değiştirir ve eşleşen CSS'yi tek bir yığın olarak yayınlar. Tarayıcıda hiçbir şey çalışmıyor.

CSS-Zero, tek bir fikir etrafında birleştirilmiş vanilla-extract (tip güvenli `.css.ts' ile sıfır çalışma süresiyle yazma) ve Tailwind CSS'den (birleştirilebilir yardımcı program/varyant sınıfları) ilham almıştır: her şey yeniden kullanılabilir bir simgedir.

Neden "yeniden kullanılabilirlik açısından iyileştirilmiş" bir CSS-in-TS? ​

Bence kodun değeri genellikle yeniden kullanılabilirliği ile ölçülebilir. CSS-Zero, stilleri karmaşıklık veya katı kısıtlamalar olmadan yeniden kullanılabilir kılma fikri üzerine inşa edilmiştir.

Tek gereklilik, stilleri .css.ts veya .css.js uzantılı dosyalarda yazmaktır. Bu noktadan itibaren, yeniden kullanılabilirlik her düzeyde temel bir kavram olarak ele alınır:

  • Yeniden kullanılabilir kurallar — className, classSelector, id, idSelector, variable, animation, font, layer ve container; özgürce bir araya getirebileceğiniz küçük ve kendi kendine yeten belirteçler (token'lar) üretir.
  • Yeniden kullanılabilir varyantlar — variants ve theme, tek bir temel stili bir dizi değiştiriciye (modifier) ​​dönüştürür; böylece bir bileşen, CSS tekrarına gerek kalmadan birçok görsel durumu karşılayabilir.
  • Yeniden kullanılabilir koşullu stiller — style(config, deps), yalnızca referans verilen belirteçler paket (bundle) içinde fiilen kullanıldığında çıktıya dahil edilen stiller tanımlamanıza olanak tanır.
  • Yeniden kullanılabilir kütüphaneler — Bir .css.ts modülü, aslında sadece standart bir modüldür. Bir stil kütüphanesini NPM'de yayınlayabilir ve diğer herhangi bir dışa aktarılan öğe gibi belirteçleri içe aktararak (import ederek), herhangi bir projede normal bir bağımlılık olarak kullanabilirsiniz. Kütüphane önceden .css.js formatına da derlenebilir; CSS-Zero her iki formatı da desteklediği için, kütüphaneyi kullanan tarafın dağıtım biçimiyle ilgilenmesi gerekmez.

Her bir yardımcı fonksiyon; düz bir metin ya da diziler veya düz nesneler içinde yer alan metinler döndürür; başka bir şey değil. Derleme aşamasında derleyici, her bir benzersiz sonucu token (ör. o-s_1, --o-v_1) adı verilen özel bir metinle değiştirir ve buna karşılık gelen CSS'i üretir. Token'lar benzersiz olduğu için kullanılmayan stiller "tree-shaking" (gereksiz kodun ayıklanması) işlemiyle elenir; böylece yalnızca gerçekten kullandığınız CSS pakete dahil edilir ve bu yeniden kullanımın çalışma zamanında (runtime) herhangi bir maliyeti olmaz.

Sonuç olarak, stili bir kez tanımlayıp her yerde yeniden kullanabilir ve yalnızca kullandığınız kısımları nihai pakete dahil edebilirsiniz.

Kurulum ​

bash
npm i @css-zero/core @css-zero/vite-plugin

Yapılandırma (Vite) ​

ts
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { cssZero } from '@css-zero/vite-plugin';

export default defineConfig({
    plugins: [react(), cssZero()],
});

Stilleri bir .css.ts dosyasında yazın ve token'ları bileşenlerinize içe aktarın.

tsx
// Button.tsx
import { btn } from './styles.css.ts';

export function Button() {
    return <button className={btn}>Click</button>;
}

Kamu Hizmetleri ​

Bireysel kurallar ​

FonksiyonİmzaDönüş Değeri
className(rule?) => stringBenzersiz sınıf belirteci (ör. o-s_1)
classSelector(rule?) => [string, string][token, '.token']
id(rule?) => stringBenzersiz kimlik belirteci
idSelector(rule?) => [string, string][token, '#token']
variable(config?) => [string, string][--token, 'var(--token)']
animation(config?) => stringBenzersiz @keyframes adı belirteci
font(config?) => stringBenzersiz @font-face ailesi belirteci
layer() => stringBenzersiz @layer token dizesi
container(type?) => [string, string][container, '@container name']

Birleşik kurallar ​

FonksiyonİmzaDönüş Değeri
variants(config, base?) => Record<string, string>Değiştirici belirteç eşlemesi, .base.mod seçicisi
theme(vars, options) => [Record, Record][varRefs, optionClasses]
style(config, deps?) => stringKüresel stiller (bağımlılık yok) veya koşullu VE öbekleri

Örnekler ​

className ​

ts
import { className } from '@css-zero/core';

export const btn = className({
    color: 'white',
    '&:hover': { color: 'gray' },
});
// → 'o-s_1'

classSelector ​

ts
import { classSelector } from '@css-zero/core';

export const [card, cardSelector] = classSelector({
    display: 'block',
    padding: '16px',
    borderRadius: '8px',
});
// card → 'o-s_1', cardSelector → '.o-s_1'

id ​

ts
import { id } from '@css-zero/core';

export const badge = id({ backgroundColor: 'red' });
// → 'o-i_1'

idSelector ​

ts
import { idSelector } from '@css-zero/core';

export const [modal, modalSelector] = idSelector({
    position: 'fixed',
    inset: 0,
});
// modal → 'o-i_1', modalSelector → '#o-i_1'

variable ​

ts
import { variable } from '@css-zero/core';

// [name, var(name)]
export const [accentKey, accent] = variable('#2b6cb0');
// → ['--o-v_1', 'var(--o-v_1)']

animation ​

ts
import { animation } from '@css-zero/core';

export const spin = animation({
    from: { transform: 'rotate(0)' },
    to: { transform: 'rotate(360deg)' },
});

font ​

ts
import { font } from '@css-zero/core';

export const inter = font({
    src: "url('/fonts/inter.woff2') format('woff2')",
    weight: '400 700',
    display: 'swap',
});
// → 'o-f_1' — use it as `fontFamily: Inter`

layer ​

ts
import { layer } from '@css-zero/core';

export const base = layer();
// → '@layer o-l_1'

container ​

ts
import { container } from '@css-zero/core';

export const [card, cardQuery] = container('inline-size');
// card → 'o-c_1 / inline-size', cardQuery → '@container o-c_1'

variants ​

ts
import { variants } from '@css-zero/core';

export const tone = variants(
    { primary: { color: '#fff' }, ghost: { color: 'gray' } },
    btn // optional base token → selector becomes `.btn.primary`
);
// → { primary: 'o-s_2', ghost: 'o-s_3' }

theme ​

ts
import { theme } from '@css-zero/core';

// [varRefs, optionClasses]
export const [tokens, options] = theme(
    { accent: '#2b6cb0', spacing: '8px' },
    { dark: { accent: '#0f0' }, compact: { spacing: '4px' } }
);
// tokens.accent → 'var(--o-v_1)'
// options.dark  → 'o-s_1' (overrides accent when applied)

style ​

ts
import { style } from '@css-zero/core';

// no deps - always emitted
style({ body: { margin: 0 } });

// emitted only if all deps are used in the bundle
style({ [`${btnSelector} > span`]: { display: 'block' } }, [btnSelector]);

TypeScript türlerini genişletme ​

Arayüz bildirimi birleştirme yoluyla kendi özel CSS özelliklerinizi birleştirin:

ts
declare global {
    namespace CSSZero {
        interface ExtraProperties {
            '--brand': string;
        }
    }
}

Stil kitaplığı yayımlama ​

Sözleşme modülleri (contract modules) sıradan modüllerdir; bu sayede stilleri bir NPM paketi olarak yayınlayabilir ve kullanabilirsiniz:

ts
// your-lib/src/buttons.css.ts
export const [btn, btnSelector] = classSelector({ /* ... */ });
export const btnBg = variants({ primary: { /* ... */ }, ghost: { /* ... */ } }, btn);
tsx
import { btn, btnBg } from 'your-lib/src/buttons.css';

<button className={`${btn} ${btnBg.primary}`}>Button</button>

Eklenti seçenekleri ​

SeçenekTürVarsayılanAçıklama
prefixstring'o'Her bir belirteç için isim ön eki (o-s_1, --o-v_1)
build.inlinebooleanfalseCSS'i <link> yerine <head> içindeki bir <style> etiketine gömün

Önemli ​

Bir paketleyici (SSR, Jest, tsc/IDE) dışında, @css-zero/core boş dizeler döndürür; imzalar doğrudur ancak değerler yer tutucudur. İşlevsel akış, @css-zero/compiler ve @css-zero/vite-plugin üzerinden ilerler.

Paketler ​

PaketRol
@css-zero/coretsc/IDE için gerçek yardımcı türler + dize şablonları
@css-zero/compilerDerleme aracı bağımsız derleme motoru
@css-zero/vite-pluginVite arayüzü: derler, birleştirir, CSS'i satır içine alır veya dışa aktarır, import'ları ayıklar

Apache Lisansı 2.0 altında yayınlanmıştır