CSS Flexbox elementi
U ovom tekstu nastavljamo objašnjavanje Flexboxa i bavimo se atributima vezanim za flex-elemente. Ako ste propustili, obavezno prvo savladajte osnovnu lekciju o Flexboxu i lekciju u kojoj se bavimo flex-kontejnerom.
Atributi kojima se ovde bavimo se odnose na podešavanje izgleda pojedinih flex-elemenata. Najviše je to kontrola njihove veličine, ali i mogućnost poravnanja i zadavanja drugačijeg redosleda:
Flex-elementi | |
---|---|
order | Redosled flex-elemenata |
flex-basis | Inicijalana veličina elementa |
flex-grow | Proporcija koja definiše koliko se flex-element može povećati u odnosu na ostale elemente |
flex-shrink | Proporcija koja definiše koliko se flex-element može smanjiti u odnosu na ostale elemente |
flex | Kompleksan atribut koji zamenjuje flex-grow, flex-shrink i flex-basis atribute |
align-self | Poravnanje pojedinog flex-elementa unutar linije, po ukrštenom pravcu |
Da se podsetimo osnovne terminologije kada radimo sa Flexbox modelom:
Kao što smo rekli, ovde se bavimo flex-elementima, odnosno atributima koji utiču na njihov izgled i raspored unutar flex-kontejnera. Naravno, i to su obični elementi, kao i svi drugi. I njima mogu biti zadati širina, visina, margine, padding, pa čak i pozicija.
Web čitač će se držati (koliko je moguće) zadatih dimenzija elementa , ali naravno, neke flexbox vrednosti poput stretch u atributima kao što su align-items ili self-align ili podešavanje flex-basis atributa, će imati uticaja na definisane dimenzije.
Zadate margine za flex-elemente nekad vrše a nekad ne vrše uticaj da se između elemenata pojave razmaci (zavisno da li je zadato pravnanje elemenata sa razmakom), dok padding uvek mora da utiče, s obzirom da se njime menjaju dimenzije elemenata.
I flex-elementi mogu biti apsolutno pozicionirani. U tom slučaju se ne "ređaju" sa ostalim elementima, pošto, kao što znamo, tada iskaču iz normalnog toka elemenata.
order
Atribut order definiše redosled flex-elemenata. Drugim rečima, ovim atributom možemo zadati drugačiji redosled u odnosu na redosled kako su flex-elementi navedeni u HTML-u. Kao vrednost moguće je navesti:
- 0 - default vrednost
- [numerik] - redosled prikaza, očekuje se pozitivan ili negativan ceo broj
Dakle, redosled prikaza će biti od najmanjeg prema najvećem zadatom broju.
order: 25;
order: -5;
Ima još jedna važna stvar - kako se ređaju elementi sa zadatim order atributom u odnosu na elemente bez ovog atributa? Pravilo je sledeće:
- prvo se ređaju elementi sa negativnim order vrednostima
- zatim se ređaju elementi bez order atributa i oni kojima je order:0, prema HTML redosledu
- na kraju se ređaju elementi sa pozitivnim order vrednostima
Znači, čak iako bismo imali npr. 100 flex-elemenata, i nekom od njih zadamo recimo order:5, on neće biti preikazan na petom mestu, već na kraju, pošto se prvo ređaju svi elementi koji nemaju zadat order, a tek onda oni koji imaju.
U stvari, za sve elemente koji nemaju zadatu order vrednost, podrazumeva se vrednost 0. Inače, svi elementi sa jednakom order vrednošću, ređaju se po redosledu kako su navedeni u HTML-u.
Primer za order
<style>
.kont {
display: inline-flex;
flex-direction: row;
align-items: center;
align-content: stretch;
}
.e2 {
background-color: #67b;
order: 3;
}
.e3 {
background-color: #67b;
order: 1;
}
.e4 {
background-color: #483;
order: -5;
}
</style>
<div class="kont">
<b>1</b>
<b class="e2">2</b>
<b class="e3">3</b>
<b class="e4">4</b>
<b>5</b>
</div>
Dakle u primeru vidimo da je najpre prikazan četvrti element, pošto ima negativnu order vrednost. Zatim se prikazuju prvi i peti element koji nemaju zadat order, i to po redosledu kako su navedeni u HTML-u. Na kraju se prikazuju treći i drugi, i to prema redosledu njihovih order vrednosti.
flex-basis
Ovaj atribut predstavlja inicijalnu veličinu flex-elementa po osnovnom pravcu. Znači ako je osnovni pravac horizontalan, flex-basis označava širinu, a ako je osnovni pravac vertikalan, flex-basis označava visinu elementa. Element će imati tu veličinu - ako je moguće. Vrednosti koje ovaj atribut "prima" su:
- auto (default) - veličina elementa se preuzima od atributa width ili height (zavisno od glavnog pravca), ako su definisani, a ako ne, onda je vrednost ista kao da smo zadali content
- [metrika] - elementu se zadaje konkretna veličina u mernim jedinicama
- [procenat] - elementu se zadaje relativna veličina u odnosu na flex-kontejner
- content - elemenat dobija veličinu na osnovu svog sadržaja
Ako se zada vrednost auto (ili se ovaj atribut uopšte ne navede, pošto je početna vrednost auto), gledaju se width ili height. Međutim, ako se "namesti" da su i dimenzije iz nekog razloga "automatske", onda se ovaj atribut ne ponaša kako bi se ponašao običan blok, već se veličina elementa određuje na osnovu njegovog sadržaja.
Zašto bismo koristili flex-basis ako je to praktično ista stvar kao kad navodimo width osdnosno height? Pa jednostavno - lakše je da imamo u vidu samo jedan atribut veličine po osnovnom pravcu, bez obzira da li je to horizontala ili vertikala, nego da mozgamo o tome kakav je pravac i da li koristimo width ili height. Posebno što se kasnije osnovni pravac flex-kontejnera može promeniti u programu, a pomoću ovog atributa se sve razrešava automatski.
Primer za flex-basis
<style>
.kont {
display: inline-flex;
flex-direction: row;
align-items: center;
align-content: stretch;
}
.k2 {
flex-wrap: wrap;
}
.e1 {
flex-basis: 0;
}
.e2 {
flex-basis: content;
}
.e3 {
flex-basis: 20px;
}
.e4 {
flex-basis: 25%;
}
.e5 {
width: 50px;
flex-basis: auto;
}
</style>
Šta se ovde sada događa? Zadali smo flex-basis za drugi i treći elemenat. Tako možemo videti kako se ovi elementi ponašaju u nekoliko različitih situacija - kada nema ili ima prelaska u novi red i kada ima ili nema viška sadržaja.
Primetite da, kada nije zadat flex-wrap:wrap (višelinijski prikaz), flex-basis vrednost se poštuje samo ako ima dovoljno mesta u redu. Ovo u stvari nema puno veze sa atributom flex-basis, već sa fleksibilnošću prikaza flexbox elemenata. Naime, atribut flex-shrink ima default vrednost 1, što omogućava elementima da se "sabiju" ako treba. Da smo želeli da se isključivo poštuje flex-basis, zadali bismo i flex-shrink:0.
Sa druge strane, kada je uključen i višelinijski prikaz, vidimo da se elementi šire onoliko koliko je zadato pošto tada nema razloga da se vrši njihovo "sabijanje" - kada nema mesta, jednostavno se pređe u novi red.
Vidimo kako vrednost content zadaje širenje prema sadržaju, dok vrednost auto "prepisuje" ono što je zadato u atributu width. Kada width ne bi bio zadat, auto bi se ponašao kao content.
flex-grow
Pomoću atributa flex-grow definišemo koliko se veličina elementa može povećati u odnosu na ostale elemente, po osnovnom pravcu. Moguće vrednosti su:
- 0 (default) - elementi se ne šire automatski
- [numerik] - broj koji označava proporciju proširenja u odnosu na ostale elemente
Numerik se zadaje bez bilo kakve merne jedinice, a dozvoljene vrednosti su pozitivni brojevi - celi i decimalni. Šta ova vrednost znači? Sama za sebe ne puno. Ali kada se posmatra u odnosu na druge elemente, označava koliko puta taj element može biti uvećan u odnosu na njih. Ako je svim elementima zadata ista flex-grow vrednost, onda će svi imati istu veličinu.
Dakle ako elementu zadamo flex-grow:2, to može da znači da je element duplo veći od ostalih, ako svi ostali imaju flex-grow:1. Ali isto tako može da znači da je element jednak drugima, ako i svi ostali imaju flex-grow:2.
Primer za flex-grow
<style>
.kont {
display: inline-flex;
flex-direction: row;
align-items: center;
align-content: stretch;
}
.e0 {
background-color: #96b;
flex-grow: 0;
}
.e1 {
background-color: #67b;
flex-grow: 1;
}
.e2 {
background-color: #6b7;
flex-grow: 2;
}
.e7 {
background-color: #b67;
flex-grow: 7;
}
</style>
U prvom okviru vidimo da se element sa grow faktorom 0 ne razlikuje od ostalih - to je zato što je po defaultu, za sve elemente flex-grow:0. Već u drugom okviru, element sa zadatim flex-grow:1 se širi tako da se zauzme sav slobodan prostor. Potpuno bi bilo isto da smo mu zadali bilo koji broj, pošto je to jedini elemenat koji se širi.
Ako imamo više elemenata sa jednakim grow faktorom, kao što je npr. slučaj u trećem okviru, ti elementi će se širiti podjednako. Opet, ni ovde ne bi bilo bitno da li smo zadali 1 i 1, 2 i 2, itd.
Međutim, u poslednja dva okvira možemo videti kako se elementi sa različitim grow faktorima različito šire. Oni elementi koji imaju veći flex-grow, širiće se više od elemenata sa manjom grow vrednošću.
Dakle, elemenat sa grow faktorom 7 neće biti sedam puta širi od elementa sa flex-grow:1. Faktori se odnose samo na to koliki "komad" pozitivnog (slobodnog) prostora se odvaja za koji elemenat, prema čemu se oni i šire.
flex-shrink
Slično kao flex-grow, atribut flex-shrink definiše koliko se veličina elementa može smanjiti u odnosu na ostale elemente (po osnovnom pravcu). Moguće vrednosti su:
- 1 (default) - svi elementi se mogu podjednako smanjiti
- [numerik] - broj koji označava proporciju umanjenja u odnosu na ostale elemente
Isto kao i kod flex-grow, vrednost je samo broj bez bilo kakve merne jedinice, a dozvoljene vrednosti su pozitivni brojevi - celi i decimalni. Ako element ima zadatu flex-shrink vrednost 0, element se neće smanjivati već će zadržati originalnu veličinu.
Kada web čitač odlučuje kako da smanji elemente, on množi flex-shrink faktor sa flex-basis vrednošću i tako dobija proporciju za umanjenje elemenata kada se raspodeljuje negativni prostor. To znači da će se "veći" elementi smanjivati brže od "manjih".
Negativan prostor može postojati samo ako ne postoji višelinijski prikaz. Drugim rečima, ako elementi imaju mogućnost da pređu u sledeću liniju, onda i ne postoji potreba da se smanjuju. Hoćete još jasnije? Ako zadamo flex-wrap: wrap, flex-shrink neće funkcionisati.
Primer za flex-shrink
<style>
.kont {
display: inline-flex;
flex-direction: row;
align-items: center;
align-content: stretch;
}
.e0 {
background-color: #96b;
flex-shrink: 0;
}
.e1 {
background-color: #67b;
flex-shrink: 1;
}
.e2 {
background-color: #6b7;
flex-shrink: 2;
}
.e3 {
background-color: #699;
flex-shrink: 3;
}
.e9 {
background-color: #b67;
flex-shrink: 9;
}
</style>
Prvi okvir nam demonstrira ponašanje flex-elementa kome je zadat shrink faktor 0. Taj element se ne sužava, a razlog što se ostali elementi sužavaju je što je default flex-shrink vrednost 1. Upravo zbog toga, u drugom okviru, element sa zadatim flex-shrink:1 izgleda potpuno isto kao i svi drugi elementi.
Zanimljive stvari se dešavaju od trećeg okvira. Tu imamo element sa zadatim flex-shrink:2 faktorom, i vidimo kako se on smanjio više od drugih elemenata. Ako dva elementa imaju isti shrink faktor (kao u četvrtom okviru), smanjiće se podjednako.
Konačno, u poslednja dva okvira vidimo kako izgledaju elementi kojima se zadaju različiti shrink faktori. Ok, ovo je važilo i u svim prethodnim okvirima, pošto su "obični" elementi po defaultu imali flex-shrink:1. Vidimo razliku kada jedan element ima flex-shrink:2 a drugi flex-shrink:3 - zaista će drugi element biti više "sužen" od drugog. U poslednjem okviru smo pokušali da pretramo, pa smo poslednjem elementu zadali flex-shrink:9. Ne pokušavajte sami da predvidite kolike će zaista da budu širine elmenata. To zavisi od dosta faktora koji se stalno menjaju (flex-basis, sadržaj, veličina kontejnera...) tako da se neki elementi možda neće suziti koliko ste očekivali.
Sve ovo ovako izgleda samo zato što nije zadat flex-wrap, pa su elementi "prinuđeni da se skupe". Kada bi bio omogućen i prikaz u više linija, svi elementi bi se raširili prema svom sadržaju.
flex
Najzad dolazimo do atributa flex, koji generalno definiše fleksibilnost elementa. Ovaj atribut je kompleksan i objedinjuje flex-grow, flex-shrink i flex-basis atribute. U svom osnovnom obliku, atribut flex se zadaje kao:
flex: grow shrink basis;
Postoji značajna razlika kada zadamo flex atribut i kada zadajemo svaki atribut pojedinačno. Vidite, kao što možemo zadati samo neke od tri navedena atributa, tako i u flex možemo zadati samo neke vrednosti. Međutim, podrazumevane (default) vrednosti se razlikuju kada ne zadamo neki atribut i kada ne zadamo neku flex vrednost.
- initial (default), tumači se kao 0 1 auto - ovo je podrazumevana vrednost
- [numerik] [numerik] [metrika] - elementu se zadaju faktori uvećanja i umanjenja i početna veličina u mernim jedinicama
- [numerik] [numerik] content - zadaju se faktori, a veličina je određena sadržajem
- [numerik] [numerik] auto - zadaju se faktori, a veličina je ono kako je zadato u flex-basis atributu, ako ga ima, inače je opet po sadržaju
- auto tumači se kao 1 1 auto
- none tumači se kao 0 0 auto
Kao što smo rekli, nije uvek potrebno zadati sve tri vrednosti i ovde dajemo moguće kombinacije i kako se one tumače. Naravno, kada se zadaje atribut, za grow i shrink navodimo numerike, a za basis vrednost navodimo metriku ili definisanu vrednost.
flex: grow shrink; // isto kao grow shrink 0
flex: grow basis; // isto kao grow 1 basis
flex: grow; // isto kao grow 1 0
flex: basis; // isto kao 1 1 basis
Ako se faktor uvećanja ili faktor umanjenja izostave, njihova podrazumevana vrednost je 1. Upravo zbog toga kada se navede flex:auto, to predstavlja vrednost flex:1 1 auto, pošto se "auto" tumači kao flex-basis vrednost. Međutim, ako se izostavi flex-basis, njegova podrazumevana vrednost je 0.
Primer za flex
<style>
.kont {
display: inline-flex;
flex-direction: row;
flex-wrap: wrap;
align-content: stretch;
align-items: center;
overflow: hidden;
}
.k1>* {
flex: initial;
}
.k2>* {
flex: 25px;
}
.k3>* {
flex: 45%;
}
.k4>* {
flex: 1;
}
.k5>* {
flex: none;
}
.k6>* {
flex: auto;
}
.k7>* {
flex: 0 50px;
}
.k8>* {
flex: 0 0;
}
</style>
Ovde smo napravili nekoliko primera za atribut flex. Vidite koliko različitih rezultata dobijamo, a flex je u svakom okviru primenjen na sve elemente. Zamislite šta bi se sve postiglo kada bismo flex primenjivali na pojedine elemente. Ovo ilustruje koliko je flexbox prikaz u stvari fleksibilan.
Upravo zbog toga, primetićete da kod zadavanja grow i shrink faktora ne idemo van zadavanja vrednosti 0 i 1. Nema svrhe zadavati veće brojeve ako se vrednost primenjuje na sve elemente - naučili smo da veličina nije bitna kada elementi imaju podjednake grow i shrink faktore. Naravno, kada bismo primenjivali flex na pojedinačne elemente, različiti grow i shrink faktori bi i te kako uticali na različite veličine elemenata.
Hajde da prođemo ukratko kroz ovih osam kontejnera.
- initial - računa se kao da smo zadali 0 1 auto, što znači da se elementi ne šire, mogu se suziti ako zafali prostor (ovde se ne dešava jer imamo višelinijski prikaz), a veličina im je prema sadržaju.
- 25px - kada zadamo samo metriku (tj. basis), kao da smo zadali 1 1 25px, što znači da će elementi dobiti širinu od 25px, ali ako ima slobodnog mesta, raširiće se da ga popune.
- 45% - opet je zadat samo basis, dakle i ovo je kao 1 1 45%, s tim što su sada elementi preširoki da bi stalo više njih u liniju, pa zato imamo samo po jedan, potpuno raširen element po redu.
- 1 - kada se zada samo jedan numerik, to je onda grow faktor i ovo se posmatra kao 1 1 0 - inicijalna širina im je minimalna, a onda se svi šire podjednako.
- none - iako se ova vrednost računa kao 0 0 auto, u ovom slučaju izgleda isto kao initial pošto shrink praktično ne utiče - ne možemo videti razliku u smanjivanju elemenata pošto imamo višelinijski prikaz.
- auto - i ovo je zadavanje samo basis faktora, dakle isto kao 1 1 auto - elementi dobijaju najpre širinu prema sadržaju, a onda se rašire da popune prostor.
- 0 50px - zadavanje numerika i metričke vrednosti znači da smo zadali grow i basis, što se računa kao 0 1 50px - elementi dobijaju podjednaku fiksnu veličinu, ali se ne šire, a zbog višelinijskog prikaza i ne sužavaju
- 0 0 - dva numerika su grow i shrink, a ovo se tumači kao 0 0 0 - širina elemenata će biti minimalna moguća, a elementi se neće ni širiti ni sužavati.
align-self
Definiše način kako će pojedini flex-elemenat biti poravnat unutar svoje linije, po ukrštenom pravcu. Praktično, ovaj atribut radi istu stvar kao align-items, samo se odnosi na pojedinačne elemente. Moguće vrednosti su:
- auto (default) - elemenat je poravnat na osnovu vrednosti align-items atributa
- flex-start - elemenat je poravnat uz početak linije po ukrštenom pravcu
- flex-end - elemenat je poravnat uz kraj linije po ukrštenom pravcu
- center - elemenat je centriran unutar linije po ukrštenom pravcu
- baseline - elemenat je unutar linije poravnat po sadržaju (tekstu)
- stretch - elemenat je razvučen na celu dimenziju linije po ukrštenom pravcu
Primer za align-self
<style>
.kont {
display: inline-flex;
flex-direction: row;
flex-wrap: wrap;
align-content: stretch;
align-items: center;
}
.e1 {
align-self: flex-start;
}
.e2 {
align-self: flex-end;
}
.e3 {
align-self: center;
}
.e4 {
align-self: baseline;
}
.e5 {
align-self: stretch;
}
</style>
Da bismo napravili razliku, svi elementi su najpre centrirani po vertikali, unutar svojih linija atributom align-items.
Kreirane klase za svaki primer, tj. atribut align-self smo primenili samo na elemente 2 i 3. Posebno obratite pažnju na vrednost baseline - Prvi takav element je poravnat kao top, a tek je onda svaki sledeći baseline element poravnat prema tekstu sa njim.
Ako vam je sve ovo jasno, i pod uslovom da ste savladali i lekciju o Flexbox kontejnerima, možete se vratiti na osnovnu lekciju o Flexbox modelu i ponovo proučiti primere koji su tamo dati.
- W3C, CSS Flexible Box Layout Module Level 1
- CSS Tricks, A Complete Guide to Flexbox
- Mozilla Developer Network, CSS Flexible Box Layout
- Can I Use, CSS Flexible Box Layout Module