Nazad na vijesti

SCSS Arhitektura: Sistem Iza Naših Tema

Dobro strukturiran SCSS kod nije samo uredan — brži je za izgradnju, lakši za održavanje i skalira bez bolova. Evo kako ga mi strukturiramo i zašto je svaka odluka donesena namjerno.

Kada projekt naraste iznad nekoliko stranica, CSS postaje prva stvar koja uzvraća udarac. Ratovi specifičnosti, duplicirane vrijednosti, breakpoint definisan u tri različita fajla. Poznata priča. Način na koji smo strukturirali SCSS u našoj Mena temi nije nastao preko noći — evoluirao je kroz stvarne projekte, stvarne rokove i stvarni bol.

Ovaj post prolazi kroz našu arhitekturu sloj po sloj: šta svaki folder radi, zašto postoji i specifični alati koji ga čine funkcionalnim. Ako gradite WordPress teme ili bilo koji CSS-intenzivan projekt, ima ovdje nešto vrijedno preuzimanja.

Struktura Foldera

Sve se nalazi unutar resources/scss/. Ulazna tačka je style.scss — jedan fajl koji ne radi ništa osim uvoziti. Nikada ne sadrži stvarna pravila. Jedini mu je posao deklarirati redosljed učitavanja koristeći moderni @use sintaksu:

@use 'abstracts'@use 'vendor/normalize'@use 'base'@use 'layout'@use 'blocks/index'@use 'components'@use 'elements'@use 'pages'

Taj redosljed je važan. Apstrakcije (varijable, mixini) moraju se učitati prije svega što ih koristi. Vendor reseti dolaze prije naše baze. Layout prije komponenti. Čita se kao graf zavisnosti jer to i jeste.

Abstracts: Sloj Design Tokena

Folder abstracts/ je mozak sistema. Sam po sebi ne outputuje nikakav CSS — čiste su deklaracije. Varijable, funkcije, mixini. Sve što drugi slojevi konzumiraju.

Varijable. Breakpointi su definirani jednom kao Sass mapa: xs: 440px, sm: 640px, md: 768px, lg: 1024px, xl: 1280px, xxl: 1536px. Boje su također mapa — i tu postaje zanimljivo. Prolazimo kroz tu mapu da automatski generiramo CSS custom properties (--color-primary) i utility klase (.color-primary, .background-primary). Jedan izvor, tri outputa.

Breakpoint mixin. Umjesto pisanja sirovih media querija svuda, imamo jedan mixin koji rukuje min-width, max-width, opsezima i prilagođenim uvjetima. @include breakpoint(md) outputuje @media screen and (min-width: 768px). @include breakpoint(xs, xl) daje opseg. @include breakpoint($to: lg) ograničava na 1023px. Jedan konzistentan API, nula magic numberova razbacanih po fajlovima.

Fluid tipografija. Ovo je jedna od tehnika o kojoj smo najpažljiviji. Umjesto skakanja između dvije fiksne veličine fonta s breakpointom, koristimo CSS calc() formulu koja čini da veličina fonta raste linearno s širinom viewporta. Naslov može biti 2.5rem na 375px i glatko dostići 3rem na 1600px — bez iznenadnog skoka, bez dodatnog breakpointa, samo glatka krivulja.

Fluid spacing. Isti princip primijenjen na margine i padding. Gornja margina .content-block-a skalira od 28px na mobilnom do 60px na desktopu. Mixin fluid-spacing() uzima naziv propertija, mobilnu vrijednost i desktop vrijednost te računa matematiku. Blokovi s pozadinama automatski dobijaju odgovarajući fluid padding.

Base: Globalni Defaultovi

Folder base/ postavlja osnovna pravila. Normalize.css najpre resetuje browserske nekonzistentnosti. Zatim naši base stilovi: box-sizing, line-height, font-family, link defaulti, margine paragrafa. Tipografija se generira programatski — definiramo mapu veličina naslova (min i max za svaki h1–h6), zatim prolazimo kroz nju primjenjujući fluid-type mixin na svaki. Dodavanje ili promjena veličine naslova je promjena jedne linije u mapi.

Fajl _helpers.scss sadrži naše utility klase: layout helpere poput .flex, .grid, spacing utilitije poput .mt-4, .gap-3 i display prečice. Ovo nisu zamjena za Tailwind — to je mali, kuriran set klasa koji pokriva 80% layout potreba bez dodavanja kompletne utility framework zavisnosti.

Layout, Komponente, Elementi

Layout rukuje strukturnim ljuskama: grid sistemom, headerom, footerom, content areom i WordPress default block stilovima. To su veliki kontejneri. Komponente su višekratni dijelovi koji žive unutar layouta: navigacioni meniji, post kartice, social linkovi. Elementi su atomski UI dijelovi: dugmad, form inputi.

Dugmad ilustruju kako koristimo BEM. Osnovna klasa je .c-button. Varijante su modifkatori: .c-button--primary, .c-button--secondary, .c-button--bordered. Ikona unutar dugmeta je element: .c-button__icon. Struktura je predvidljiva. Kada developer vidi .c-button--primary, tačno zna gdje da traži u SCSS stablu.

Blocks: Gutenberg Sloj

Folder blocks/ je poseban za naš WordPress setup. Svaki prilagođeni Gutenberg blok dobija vlastiti SCSS partial, i taj partial se automatski registrira kada se novi blok scaffolduje putem naše create-block.js skripte. Fajl blocks/index.scss se ažurira automatski — developeri ga nikada ručno ne diraju.

Stilovi blokova su izolirani. Stilovi jednog bloka ne iscuravaju u druge blokove. Ovo je kritično kako tema akumulira 20, 30 ili 50 blokova — trebate povjerenje da promjena CSS-a jednog bloka neće stvoriti neočekivane efekte negdje drugdje.

Zašto @use Umjesto @import

Cijeli sistem koristi moderne @use i @forward API-je umjesto legacy @import-a. Ovo nije samo preferencija — rješava stvarni problem. Sa @import-om, svaka varijabla, mixin i funkcija bila je globalno dostupna svugdje. To zvuči zgodno sve dok ne debugujete specificity problem uzrokovan mixinom za koji niste znali da se primjenjuje.

Sa @use-om, svaki fajl eksplicitno deklarira šta mu treba. Ništa se ne uvlači tiho. Fajl komponente kojoj treba breakpoint mixin piše @use '../abstracts' as * na vrhu. To je njen ugovor zavisnosti. Sistem je transparentan, a ta transparentnost čini refaktorisanje sigurnim.

Isplata

Dobro strukturiran SCSS sistem donosi dividende na tri načina. Brzina: developeri tačno znaju gdje staviti nove stilove i gdje naći postojeće. Nema traženja, nema nagađanja. Konzistentnost: spacing, tipografija i boje dolaze iz jednog izvora istine. Promjena primarne boje je promjena jedne linije u _variables.scss. Mogućnost održavanja: kada se projekt vrati šest mjeseci kasnije za ažuriranja, kod je još uvijek navigabilan. Ne preuzimate nered.

SCSS Mena teme nije savršen — nijedan sistem nije. Ali svaka odluka u njemu je donesena namjerno, a ta namjernost je ono što razdvaja codebase koji skalira od onog koji se uruši pod vlastitom težinom.