nav_dugme codeBlog codeBlog
  • početna Početna stranica
  • Sačuvani članci Sačuvani članci
  • Članci
     (spisak)
  • Kontakt
Povratak na vrh stranice

Info & povezani članci Info o članku - dugme

Info

trejler_sat Datum objave: 03.04.2021.

trejler_dokument Jezici: CSS

trejler_teg_narandzasti Težina: 6/10

CSS
sass
web dizajn
internet
optimizacija
frontend
fullstack
teorija
saveti
zanimljivosti

Povezani članci

Uvod u web dizajn - 1. deo - Početni koraciUvod u JavaScript i DOM (Document Object Model)Tutorijal - Formular za pretraguCSS - @supports - Provera podržanosti svojstavaUpotreba specijalnih znakova u HTML datotekamaUvod u PHP i backend programiranjeLokalno skladištenje podataka browsera (sessionStorage, localStorage, cookies)Šablonske niske u programskim jezicimaASCII, UNICODE i UTF - Predstavljanje znakova na računarimaKako napraviti syntax highlighter
Svi članci
In order to understand recursion, one must first understand recursion
Anonymous

Promenljive u CSS-u (pretprocesori i imenovana svojstva)

Facebook LinkedIn Twitter Viber WhatsApp E-mail
zoom_plus zoom_minus bookmark
početna > Članci > Teorija

Uvod

Nedugo nakon što je CSS ušao u upotrebu i zauzeo mesto kao jedna od osnovnih tehnologija u web dizajnu, počelo je da se "razmišlja naglas" o tome kako samom jeziku nedostaju promenljive (preko kojih bi CSS kodovi, koji su uglavnom čitki i pregledni - mogli postati još pregledniji).

Realizacija ideja o uvođenju promenljivih, u početku je 'tapkala u mestu', ali, posle nekog vremena (sredinom 2000-ih), prvo su u upotrebu uvedeni pojedini pretprocesori za CSS (od kojih su neki popularni i dan-danas), a 2017. godine (mnogi programeri bi rekli "konačno"), u specifikaciju samog jezika CSS uvrštena su i tzv. imenovana svojstva - "ne baš prave promenljive", ali - "prilično blizu".

U nastavku, osvrnućemo se na prednosti i (ni iz daleka 'zabrinjavajuće') nedostatke, oba navedena pristupa ....

Svrha promenljivih u CSS-u

Pretpostavljamo da je sasvim jasno na koji način bi upotreba promenljivih u CSS-u doprinela unapređenju preglednosti koda (u opštem smislu), i olakšala posao programerima, ali, razmotrićemo ipak (u svojstvu primera), jednu jednostavnu i uobičajenu situaciju.

Zamislićemo da se boja #4477ee koristi na određenom sajtu - za više različitih elemenata (prikazaćemo kod za navigacionu traku, dugmad i linkove, ali, zamislićemo da selektora ima mnogo više):

		
nav.#traka_header {
	background: #4477ee;
}

.dugme {
	background: #4477ee;
}

.linkovi {
	color: #4477ee;
}
		
	
Slika 1. - Primer - CSS kod u kome je potrebno ručno menjati određenu vrednost koja se pojavljuje na više mesta.

Problem može nastati ukoliko je potrebno naknadno menjati navedeni hex kod za boju, na svim mestima, a glavno pitanje je (naravno), kako najefikasnije rešiti problem.

Posao ažuriranja CSS koda svakako bi se mogao obavljati ručno - ako bi kod doslovno obuhvatao jednu vrednost i tri selektora, ali - za razliku od gornjeg primera - na ozbiljnijim sajtovima na kojima se slični selektori javljaju u mnogo većem broju (i gotovo je sigurno da su raspoređeni u nekoliko različitih CSS datoteka), posao ažuriranja nije baš skroz "lagan i kratkotrajan".

U programskim jezicima kao što su C, Java ili Python (naravno, i u mnogim drugim programskim jezicima), sličnu situaciju bismo rešili upotrebom promenljivih, ili imenovanih konstanti (pri čemu bi promenljiva ili konstanta bila deklarisana i inicijalizovana na jednom mestu, na drugim mestima u kodu pozivali bismo se na navedenu promenljivu ili konstantu, a ažuriranje vrednosti tipično bi podrazumevalo izmenu u okviru jedne linije koda).

Na primer (u programskom jeziku C):

		
#include<stdio.h>
#define GRANICA 200

void main()
{
	int i, n

	scanf("%d", &n);

	if (n > GRANICA) {
		printf("Uneta vrednost prelazi dozvoljenu granicu!");
		return;
	}

	int a[n];
	
	for (i = 0; i< n; i++) {
		scanf("%d", &a[GRANICA]);
	}
}
		
	
Slika 2. - Primer - U programskim jezicima kao što je C, koriste se promenljive i imenovane konstante, te stoga nije potrebno (u primerima koji u idejnom smislu nalikuju primeru sa slike #1), ručno menjati vrednosti (već se sve može obaviti izmenom jedne linije koda).

.... vrednost promenljive (preko koje se određuje broj elemenata niza), unosi korisnik, dok je maksimalan broj elemenata određen preko imenovane konstante GRANICA, i obe vrednosti se mogu menjati (na veoma pregledan način).

Razmotrićemo koliko se u okvirima CSS-a možemo približiti prikazanom nivou 'fleksibilnosti', za početak, uz upotrebu pretprocesora.

CSS pretprocesori

CSS pretprocesori su programi koji omogućavaju generisanje ('običnih') CSS datoteka, korišćenjem sintakse koja predstavlja kombinaciju: običnog CSS-a, imenovanih promenljivih i drugih jezičkih konstrukcija.

Da bismo što bolje razumeli pretprocesore koji se specifično koriste za sintaksu CSS-a, podsetićemo se prvo, preko primera sa kakvima smo se susretali u ranijim člancima, čemu (inače) služe pretprocesori u prevođenju računarskih jezika.

Opšta uloga pretprocesora u računarskim jezicima

Za primer, uzećemo programski jezik C, i razmotrićemo na koji način pretprocesor reaguje na pretprocesorske direktive #include i #define (koje smo koristili u prethodnim primerima):

  • direktiva #include podrazumeva uključivanje (to jest 'uvoz') određene biblioteke (u gornjem primeru, uvezena je biblioteka stdio.h, koja sadrži funkcije printf i scanf)
  • direktiva #define predstavlja uputstvo pretprocesoru da svaku pojavu niske GRANICA (u programskom kodu), treba zameniti niskom "20" - pre početka drugih operacija

Kažemo niska, jer - dok proces prevođenja ne počne - ono što mi (kao ljudi) zapažamo kao broj 20, za kompajler je još uvek samo niska "20".

Direktiva #include funkcioniše (manje-više) po principu "copy-paste", to jest, doslovno podrazumeva kopiranje sadržaja biblioteke u programski kod koji je korisnik zapisao (to nećemo prikazivati), dok direktiva #define (za nas u ovom trenutku mnogo zanimljivija), svodi sledeći kod ....

		
if (n > GRANICA) {
	// ....
}
		
	
Slika 3. - Naredba grananja u jeziku C, pre prolaska kroz pretprocesor.

.... na konačni oblik ....

		
if (n > 20)  
	// ....
}
		
	
Slika 4. - Naredba grananja u jeziku C, posle prolaska kroz pretprocesor.

Pošto smo razumeli prethodno opisani princip, takođe neće biti teško da razumemo (skoro nimalo različit) princip funkcionisanja CSS pretprocesora.

Princip funkcionisanja CSS pretprocesora (osnovne mogućnosti)

U skladu sa prethodno navedenim principima, osnovni koncept upotrebe pretprocesora zarad generisanja CSS kodova, moguće je opisati na sledeći način:

  • na početku je potrebno definisati "promenljive" - preko pretprocesorskih direktiva (kao i obično, promenljive su predstavljene preko identifikatora, koji su povezani sa konkretnim vrednostima)
  • u "posredničkom CSS kodu" * se zatim mogu pozivati identifikatori prethodno definisanih "promenljivih"
  • pre objavljivanja sajta, potrebno je pokrenuti CSS pretprocesor koji će kompajlirati 'posrednički' kod i kreirati običan CSS kod (u kome su imenovane vrednosti koje su prethodno bile zadate preko identifikatora - zamenjene pripisanim vrednostima)

Takođe (kao što smo ranije pomenuli), moguće je koristiti i druge jezičke konstrukcije, na šta ćemo se osvrnuti u sledećem odeljku članka.

* Kada kažemo "CSS kod", u kontekstu diskusije o pretprocesorima za CSS sintaksu, mislimo na (posrednički) kod koji se većim delom poklapa sa običnim CSS-om, ali, sadrži i dodatne elemente, koji nisu direktno prepoznati u browserima - već se moraju kompajlirati.

Za primer ćemo koristiti sintaksu popularnog pretprocesora SASS (Syntactically Awesome Style Sheet).

- Svojstva se definišu u datoteci sa ekstenzijom .sass:

		
$pozadina_body:     #fff;
$pozadina_dugme:    #ea4;
$boja_teksta_body:  #202020;
$boja_teksta_dugme: #fff;

body {
	background: $pozadina_body;
	color:      $boja_teksta_body;
}

.dugme {
	background: $pozadina_dugme;
	color:      $boja_teksta_dugme;
}
		
	
Slika 5. - SASS datoteka preko koje se može generisati običan CSS kod.

- Po potrebi, .sass datoteka se kompajlira preko pretprocesora - pri čemu je rezultat običan CSS kod ....

		
body {
	background: #fff;
	color:      #202020;
}

.dugme {
	background: #ea4;
	color:      #fff;
}
		
	
Slika 6. - CSS kod koji je generisan preko .sass datoteke sa prethodne slike.

.... koji se dalje može koristiti isto kao i bilo koji standardni CSS kod koji je "pisan ručno".

Dodatne mogućnosti CSS pretprocesora

Iako članak nije posvećen pretprocesoru SASS, pogledajmo još nekoliko (naprednijih) mogućnosti ovog pretprocesora.

Recimo, preko tzv. mixin klasa (i direktive @include), može se lako kreirati nekoliko sličnih CSS selektora.

Prvo je potrebno zapisati kod u datoteci sa ekstenzijom .sass ....

		
@mixin dugme_generator($sirina, $visina, $pozadina) {
	width:       $sirina;
	height:      $visina;
	background:  $pozadina;
	border:      none;
	font-weight: bold;
}

.dugme_crveno {
  @include dugme_generator(240px, 56px, #e74);
}

.dugme_zeleno {
  @include dugme_generator(240px, 56px, #4e7);
}

.dugme_plavo {
  @include dugme_generator(240px, 56px, #47e);
}
		
	
Slika 7. - SASS kod sa "mixin" klasom koja služi kao obrazac za generisanje CSS koda.

.... posle čega se kod "provlači" kroz pretprocesor, što kao rezultat daje sledeći "običan" CSS kod:

		
.dugme_crveno {
	width:       240px;
	height:      56px;
	background:  #e74;
	border:      none;
	font-weight: bold;
}

.dugme_zeleno {
	width:       240px;
	height:      56px;
	background:  #e74;
	border:      none;
	font-weight: bold;
}

.dugme_plavo {
	width:       240px;
	height:      56px;
	background:  #e74;
	border:      none;
	font-weight: bold;
}
		
	
Slika 8. - CSS kod koji nastaje kompajliranjem .sass datoteke sa prethodne slike.

Verujemo da nije teško uvideti svu lepotu pristupa koji podrazumeva generisanje običnog CSS koda (koji se može direktno koristiti u browseru), preko naočitog, sažetog koda sa imenovanim vrednostima (praktično - promenljivama), i različitim obrascima koji dodatno olakšavaju generisanje CSS kodova.

Međutim, CSS pretprocesori imaju i jednu (očiglednu) "manu": izrada sajta uz upotrebu pretprocesora - zahteva instalaciju i upotrebu dodatnog specijalizovanog programa (SASS takođe zahteva i instalaciju Ruby servera) - što je možda nešto što, određeni web developeri, u određenim situacijama - ipak žele da izbegnu.

Imenovana svojstva (custom properties) i funkcija var

Ukoliko pristup koji zahteva dodatne programe (SASS, Ruby i sl), predstavlja problem, zbog čega je potrebno ostati u okviru onoga što nudi sam CSS (bez dodataka), moguće je definisati imenovana svojstva (to jest - "prilagođena svojstva"), koja se naknadno mogu pozivati preko funkcije var.

Da, da - u CSS-u ima funkcija (ali u pitanju su jednostavne 'utilističke' funkcije). :)

Navedeni pristup ne zahteva pretprocesor (što je svakako prednost), ali, i u slučajevima kada se koriste imenovana svojstva, postoji jedan nezanemarljiv nedostatak - imenovana svojstva nisu podržana u starijim verzijama browsera (pre svega mislimo na Internet Explorer, pre verzije Edge).

Definisanje i pozivanje imenovanih svojstava

Sav kod koji se tiče imenovanih svojstava, može se zapisati u jednoj CSS datoteci (ali - kao i obično - preporučljivo je da veći blokovi koda, zarad preglednosti, budu podeljeni u zasebne datoteke, kao i to da najopštiji delove koda budu izdvojeni u zasebnu konfiguracionu datoteku i sl):

		
:root {
	--pozadina_body:     #fff;
	--pozadina_dugme:    #ea4;
	--boja_teksta_body:  #202020;
	--boja_teksta_dugme: #fff;
}

body {
	background: var(--pozadina_body);
	color:      var(--boja_teksta_body);
}

.dugme {
	background: var(--pozadina_dugme);
	color:      var(--boja_teksta_dugme);
}
		
	
Slika 9. - CSS kod koji koristi imenovana svojstva (koja se naknadno pozivaju preko funkcije var).

U selektoru za pseudoklasu :root definisano je nekoliko imenovanih svojstava, koja se zatim - preko funkcije var - pozivaju u drugim selektorima (body i .dugme).

Ovoga puta, za razliku od situacije kada smo koristili pretprocesor, nema kompajliranja ("sve što treba je tu"), a browseri (računajući i Edge, novu verziju Internet Explorera), već duže vreme podržavaju imenovana svojstva - i stoga će elementi biti uredno prikazani.

Ili - možda neće?!

U (čuvenih) "99% slučajeva", gornji kod je dovoljan, ali (da se podsetimo): ukoliko se sajt otvara na starijem računaru koji koristi stariju verziju određenog browsera (pogotovo ako je u pitanju neka od starijih verzija Internet Explorera, kod kojih je podrška za imenovana svojstva 'demonstrativno izostavljena'), elementi neće biti prikazani na očekivani način.

Web dizajneri mogu odlučiti (iz praktičnih razloga), * da prestanu sa pružanjem podrške za starije verzije browsera, ili - u skladu sa popularnom pošalicom koja navodi da je Internet Explorer browser čija je svrha da omogući preuzimanje drugih browsera sa interneta - mogu i ukinuti podršku za starije verzije Internet Explorera; ali, postoje (naravno) elegantniji načini da se problem reši.

.... s tim da ipak valja napomenuti da rešenja koja ćemo prikazati - nisu baš skroz elegantna.

* Sa strane 'osnovne ljudske pristojnosti' (i van konteksta šale i humora), ne zalažemo se za ukidanje podrške korisnicima (pre svega zarad starijih korisnika koji legitimno imaju poteškoća u savladavanju novih tehnologija, i stoga se teško odriču starijih verzija programa sa kojima su upoznati).

Međutim, u praktičnom smislu, usklađivanje sajta sa (veoma) starim verzijama browsera (tako da sve "nekako proradi"), objektivno može biti prilično naporan poduhvat (pogotovo u situacijama kada, na primer, jedan web dizajner samostalno održava sajt, to jest, u situacijama kada ne postoji osoba koja je specifično zadužena (samo) za očuvanje kompatibilnosti sajta sa starijim verzijama programa u kojima se sajtovi otvaraju).

Prvi način da se "saniraju posledice nepodržanosti svojstava", može biti - korišćenje direktiva @supports i @supports not:

		
@supports (--css: variables) {
	:root {
		--pozadina_body:     #fff;
		--pozadina_dugme:    #ea4;
		--boja_teksta_body:  #202020;
		--boja_teksta_dugme: #fff;
	}
	
	body {
		background: var(--pozadina_body);
		color:      var(--boja_teksta_body);
	}
	
	.dugme {
		background: var(--pozadina_dugme);
		color:      var(--boja_teksta_dugme);
	}
}

@supports not (--css: variables) {
	body {
		background: #fff;
		color:      #202020;
	}
	
	.dugme {
		background: #eb3;
		color:      #fff;
	}
}
		
	
Slika 10. - CSS kod sa slike #9, prepravljen tako da omogući kompatibilnost sa browserima koji ne podržavaju imenovana svojstva - metoda #1.

.... međutim - iako jesu u pitanju "zvanični" mehanizmi namenjeni rešavanju (baš) ovakvih situacija - jedan selektor (na primer body), mora se pojaviti u kodu dva ili više puta. *

Problemi u navedenom pristupu su sledeći:

  • ako se kod zapiše dvaput (jednom unutar direktive @support, a drugi put unutar direktive @supports not), oba puta mora se navesti sav kod
  • ako se zajednički delovi izdvoje u zaseban selektor, koji nije obuhvaćen direktivama @supports ili @supports not (npr. onako kako smo prikazali u uvodnom članku o CSS direktivi @supports) - ponovo smo kreirali (bar) dva selektora

* Postoje i "varijacije na temu" za oba navedena pristupa (selektor se može pisati i tri puta), ali, "kako god da okrenemo", kod koji se generiše, u praktičnom smislu je nepregledan i neelegantan.

Drugi način (koji sam po sebi takođe nije 'skroz elegantan', ali ipak bismo rekli da je znatno elegantniji), podrazumeva (u praktičnom smislu) .... korišćenje opštih principa interpretacije CSS-a u browserima.

Ukoliko se u selektoru dvaput navede određeno svojstvo, prvo navođenje svojstva (zapravo, ne samo prvo, već - "svako osim poslednjeg") - jednostavno će biti zanemareno (i time je problem podržanih/nepodržanih imenovanih svojstava, praktično rešen):

		
:root {
	--pozadina_body:     #fff;
	--pozadina_dugme:    #ea4;
	--boja_teksta_body:  #202020;
	--boja_teksta_dugme: #fff;
}

body {
	background: #fff;
	background: var(--pozadina_body);
	color:      #202020;
	color:      var(--boja_teksta_body);
}

.dugme {
	background: #eb3;
	background: var(--pozadina_dugme);
	color:      #fff;
	color:      var(--boja_teksta_dugme);
}
		
	
Slika 11. - CSS kod sa slike #9, prepravljen tako da omogući kompatibilnost sa browserima koji ne podržavaju imenovana svojstva - metoda #2.

Ukoliko browser podržava imenovana svojstva (koja su navedena), desiće se sledeće:

  • pri prvoj dodeli vrednosti određenom svojstvu (uzećemo za primer boju pozadine dugmeta), browser će upamtiti vrednost (dugme dobija boju pozadine #eb3)
  • pri drugoj dodeli vrednosti, prethodna vrednost biće zanemarena (dugme dobija novu boju - #ea4)

Navedeni pristup možemo smatrati svojevrsnom simulacijom (nimalo retke) situacije u kojoj smo "zaboravili" da ručno ažuriramo hardkodirane vrednosti atributa.

Ukoliko browser (sa druge strane), ne podržava imenovana svojstva (ponovo posmatramo boju pozadine dugmeta), desiće se sledeće:

  • pri prvoj dodeli vrednosti browser će upamtiti vrednost (i ovoga puta dugme dobija boju pozadine #eb3)
  • pri drugoj dodeli vrednosti - budući da browser ne prepoznaje funkciju var - biće zanemaren ceo red CSS-a i prethodna vrednost će biti očuvana (boja dugmeta je i dalje #eb3)

Ovakav kod jeste pomalo redundantan (tj. nije baš skroz elegantan), ali - ukoliko je potrebno održati kompatibilnost sa starijim verzijama i/ili nepodržanim browserima - u pitanju je sasvim prihvatljiva opcija.

Opseg definisanosti imenovanih svojstava

Mogli ste primetiti da su u prethodnim primerima imenovana svojstva bila deklarisana unutar selektora :root - što znači da se navedena svojstva mogu koristiti u svim selektorima.

Pored navedenog pristupa (koji je daleko najuobičajeniji), imenovana svojstva mogu se definisati i unutar drugih selektora (najbolje ipak - i u takvim situacijama - na početku datoteke), čime se opseg definisanosti imenovanih svojstava sužava.

Ako definišemo sledeća imenovana svojstva:

		
p {
	--vertikalni razmak:
}

aside div > a {
	--boja_slova:             #47e;
	--velicina_fonta_desktop: 12pt;
	--velicina_fonta_mob:     11pt;
}

main {
	--velicina_fonta_desktop: 13pt;
	--velicina_fonta_mob:     12pt;
}
		
	
Slika 12. - Imenovana svojstva koja nisu definisana u okviru selektora :root, već, u specijalizovanim selektorima.

.... i pozovemo ih naknadno u drugim selektorima, dobićemo sledeći rezultat (objašnjenja su u komentarima):

		
main {
	....
	
	// U selektoru main (koji nije obuhvaćen
	// media query direktivom), primenjujemo
	// "mobile-first" pristup i definišemo
	// veličinu fonta za mobilnu verziju sajta.

	// Svojstvo će biti uredno prepoznato.

	font-size:   12pt;
	font-size:   var(--velicina_fonta_mob);
	font-weight. normal;
	
	....
}

aside p {
	....

	margin:     20px 16px 24px 24px;

	// Ovoga puta, budući da nismo ručno
	// ažurirali vrednost atributa font-size
	// i budući da imenovano svojstvo
	// --velicina_fonta_mob važi samo za
	// elemente u okviru tagova main, slova u
	// paragrafima u okviru tagova aside će
	// biti premala.

	font-size:	10pt;
	font-size:	var(--velicina_fonta_mob);

	....
}

aside h2 > a {
	....

	// Preko svojstva --velicina_fonta_mob,
	// ovoga puta definišemo 11pt kao veličinu
	// fonta (pri čemu se naravno koristi svojstvo
	// --velicina_fonta_mob koje važi unutar
	// selektora aside h2 > a), dok će u
	// gornjem selektoru (main), veličina fonta
	// biti 12pt.
	
	font-size: var(--velicina_fonta_mob);
}

.dugme {
	background: #eb3;
	background: var(--pozadina_dugme);
	color:      #fff;
	color:      var(--boja_teksta_dugme);
}
		
	
Slika 13. - Primeri upotrebe imenovanih svojstava sa prethodne slike.

Kao što smo već naveli, u praksi preovladava pristup koji podrazumeva imenovanje svojstava u okviru opsega :root, ali, razume se da dodatne opcije sasvim dobro dođu.

Za kraj ....

Namera nam je bila da u relativno neobimnom članku predstavimo dva pristupa koji omogućavaju upotrebu 'promenljivih' u CSS-u (na način koji je, doduše, prilično različit u odnosu na pristup koji je svojstven jezicima kao što su C, Java i sl), međutim, ovoga puta nismo hteli da zalazimo u detalje (u većoj meri).

Naprednim opcijama CSS pretprocesora (sa jedne strane) i upotrebi imenovanih svojstava u JavaScript-u (sa druge strane), svakako ćemo i u budućnosti posvećivati pažnju ....

Autor članka Nikola Vukićević Za web portal codeblog.rs
Napomena: Tekstovi, slike, web aplikacije i svi ostali sadržaji na sajtu codeblog.rs (osim u slučajevima gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta codeblog.rs i zabranjeno je njihovo korišćenje na drugim sajtovima i štampanim medijima, kao i bilo kakvo drugo korišćenje u komercijalne svrhe, bez eksplicitnog pismenog odobrenja autora.
© 2020-2025. Sva prava zadržana.
Facebook LinkedIn Twitter Viber WhatsApp E-mail
početna > Članci > Promenljive u CSS-u (pretprocesori i imenovana svojstva)
codeBlog codeBlog
Sajt posvećen popularizaciji kulture i veštine programiranja.
Napomena: Tekstovi i slike na sajtu codeblog.rs (osim u slučajevima, gde je drugačije navedeno) predstavljaju intelektualnu svojinu autora sajta codeblog.rs i zabranjeno je njihovo korišćenje na drugim sajtovima i štampanim medijima, kao i bilo kakvo drugo korišćenje u komercijalne svrhe, bez eksplicitnog odobrenja autora.
© 2020-2025. Sva prava zadržana.
Facebook - logo
Instagram - logo
LinkedIn - logo
Twitter - logo
E-mail
Naslovna
   •
Uslovi korišćenja
   •
Obaveštenja
   •
FAQ
   •
Kontakt