Ne mogu da kažem da mi je problem baš iz stvarnog sveta (čitaj: sa posla), ali malo me zainteresovalo kako da rešim „situaciju“ i evo o čemu se radi, da ne dužim mnogo:
- Na stranici se nalaze dve kolone (kao dva novinska stupca), koje ne moraju biti iste širine.
- Potrebno je da oba stupca popunjavamo iz jednog izvora podataka (npr. prikazujemo vesti: prvo najsvežiju vest, pa dalje one starije), ali tako da popunjavanje ide ravnomerno i bez ograničenja visine pojedinačnog elementa (vidi dalje za objašnjenje).
- Ja nemam pojma da li ovo može da se uradi uz korišćenje samo CSS-a (nisam baš na ti sa bilo čim vezanim za /web/ dizajnerske tehnologije /a gde ja ubrajam npr. CSS, HTML i JavaScript/). Ako može, pa lepo da može. Kako? :)
Problem, za nekog ko se makar malo bavi veb dizajnom i sličnim, sigurno izgleda smešno, ali ako sa pomenutim tehnologijama ne stojite baš najbolje (dakle, u poslednjoj ste klupi, kao i ja, poklopili ste se ušima i ćutite, tj. imate, što bi se reklo, jeftiniju ulaznicu :D), može da bude interesantno, koliko god se na kraju pokaže kao - jednostavno. Dakle, pošto sam završio sa pravdanjem, da se bacimo na posao.
Pogrešno rešenje
Krećemo sa stranicom na kojoj imamo dve kolone, popularni 2-column layout, koje ne moraju biti iste širine. Slikovito:
I potrebno je da prikažemo elemente (npr. vesti) koristeći obe kolone, novije vesti na vrhu. Da pojasnimo zašto jednostavno popunjavanje po principu „jedna vest levo, jedna desno“ nikako ne odgovara pa će biti jasnije kako dolazumo do onog ravnomernog popunjavanja.
Pošto je uslov da pojedinačni elementi (vesti) ne moraju biti iste veličine (visine), onda lako možemo doći u sledeću situaciju (vesti su ubačene po sistemu „levo-desno“: 1-levo, 2-desno, 3-levo, 4-desno):
A to nam baš ne treba: ne samo da popunjavanje nije ujednačeno, nego, ako su vesti npr. poređane hronološki prilikom dovlačenja iz baze podataka („1“ je najnovija vest, a „4“ najstarija), doći ćemo u situaciju kao gore – vest „4“ je „iznad“ vesti „3“ iako ne bi trebala da bude, jer je vest „3“ svežija. Novije vesti trebaju biti što više „gore,“ bliže vrhu stranice, a ovde to nije slučaj sa vestima „3“ i „4.“ Jednostavno, popunjavanje tipa „levo-desno“ ne ide, jer mi prikazujemo elemente u celosti - ništa ne skraćujemo.
Mama u boji (rešenje)
Vraćamo se na početak, dakle. Treba nam bolji sistem raspodele vesti između stupaca.
Prva vest, označena sa „1“ na slici gore, ide u levi stupac, a druga onda, naravno, ide u desni stupac, kako bi popunjavanje bilo ravnomerno. Primetite da vest „1“ ne mora da bude iste visine (dužine, kako hoćete) kao vest „2,“ a ni stupci ne moraju biti jednake širine. Sve ostaje isto kao i pre (inače bi rešenje bilo trivijalno, kao i problem).
Fazon je, da sledeća, treća vest, ponovo ide u desni stupac, ovako:
Vest dakle ide u onaj stupac gde ima više mesta, tj. gde je manje zauzetog prostora, po vertikali. Tek sada, pošto je niz vesti u levom stupcu kraći nego u desnom, sledeća vest može da ide levo, ovako:
I tako dalje redom (peta vest bi išla desno) . Dakle, problem se svodi na to kako odlučiti da li vest treba da ide u levi ili desni stupac – nama je potrebno rešenje koje sledeći element (vest) stavlja u onu kolonu gde je trenutno manje zauzetog prostora po vertikali.
Implementacija
Dakle, rešenje je već dato, sad ostaje samo da još očas posla pokažem kako konkretno isprogramirati isto.
Naravno, nije problem kada se stvari sagledaju slikovito, osim jednog detalja: za ovo rešenje ja sam koristio JavaScript (na klijentu naravno) i nešto mi se čini da su sva rešenja koja bi se oslanjala na implementaciju na serveru (npr. da za svaku vest brojimo reči, slova ili čak redove, pa pretpostavljamo visinu fontova i tako računamo visinu cele vesti na serveru) ili zamršena ili neprecizna.
Rešenje sa JavaScript-om svakako nije savršeno, ali, kako sam već rekao, ja lično ne znam kako bih ovo rešio bez istog, uz samo CSS. Ako neko zna (da li je uopšte moguće?) – ostavite komentar.
Rešenje se svodi na jednostavno dovlačenje elemenata (npr. vesti) na stranicu i zatim njihovo ubacivanje u levu ili desnu kolonu. Kako ćete vesti dovući, manje je bitno (prilikom kreiranja same stranice ili kasnije, koristeći Ajax), a da li će vest da ide levo ili desno, odluči se tako što se proveri .offsetHeight vrednost za oba stupca i vest ide tamo gde je ova vrednost manja (u slučaju jednakosti, prednost dajemo npr. levoj koloni kako bi prva vest išla u nju). Otprilike ovako:
<div id="left"></div>
<div id="right"></div>
...
function postaviVesti()
{
var vest = new Array();
vest[0] = "<div>Prva vest...</div>";
vest[1] = "<div>Druga vest..</div>";
leftColumn = document.getElementById("left");
rightColumn = document.getElementById("right");
for( i = 0; i < vesti.length; i++ )
{
leftHeight = leftColumn.offsetHeight;
rightHeight = rightColumn.offsetHeight;
if ( leftHeight <= rightHeight )
left.innerHTML += vest[i];
else
right.innerHTML += vest[i];
}
}
Potrebno je samo obratiti pažnju da se ovakva funkcija izvrši nakon što je stranica učitana u potpunosti, tj. stilovi primenjeni, jer inače može da dođe do pogrešnog izračunavanja visina stupaca nakon ubacivanja elemenata (vesti), usled toga što CSS stil, naravno, može da postavi ove kolone na različitu širinu ako se primeni nakon što ovaj kod gore već ubaci elemente kako treba. Ova stvar je izražena kod Safari i Chrome brauzera (kada je CSS definisan van same stranice, u posebnom fajlu, kako je već običaj). Dakle, obratite pažnju na ovakav detalj (biblioteka kao jQuery, mislim, ovakvo nešto podrazumeva, pa bi trebali biti pošteđeni sitnog zezanja, ako je koristite).
Gotov primer možete da pogledate ovde, a meni ostaje da razgovaram sa kolegom i možda nešto uradimo po pitanju naslovne stranice ovog sajta - desna kolona (sa tekstovima) nešto je statična, pa možda ovakva promena ne bi bila loša :D