Incredibil ce frumos si original calareste baiatul asta chitara… Pentru cine a tinut vreodata o chitara in mana, tipul e ori geniu ori eretic.
Archives for : February2007
Exista unele situatii cand ai nevoie de o structura tabelara, dar esti obligat s-o faci din DIV-uri (a lucra pentru un tip ca mine poate impune uneori si situatii de-astea aparent absurde 😀 ). Ce faci atunci?
Poi… DACA FOLOSESTI FF, atunci poti sa reproduci structura tabelului, doar ca in loc de
< table >
< tr >
< td >
< / td >
< td >
< / td >
< / tr>
< tr>
< td >
< / td >
< td >
< / td >
< / tr>
< table >
o sa scrii ceva de genul
< div class = " table " >
< div class = " tr " >
< div class = " td " > < / div >
< div class = " td " > < / div >
< / div >
< div class = " tr " >
< div class = " td " > < / div >
< div class = " td " > < / div >
< / div >
< / div >
…iar mai departe o sa te asiguri ca definitiile celor trei noi clase vor contine urmatoarele proprietati:
.table { display: table; }
.tr { display: table-row; }
.td { display: table-cell; }
De ce? Pentru ca, setand proprietatile astea, latimile coloanelor se vor transmite in sus/jos exact ca intr-un tabel normal.
Dezavantaje:
1. treaba asta nu permite merging-ul (lipirea) de celule… cu alte cuvinte, colspan si rowspan ies din joc la abordarea asta.
2. codul html in mod cert rezulta mai lung
3. alinierea pe verticala este specifica doar celulelor de tabel real, cu abordarea asta deci o sa ai ca default numai valign=top;
4. proprietatile CSS din exemplul asta NU sunt suportate de IEx… nici nu stiu daca asta e un dezavantaj sau un avantaj 😀
Avantaje:
1. un mai bun control asupra celorlalte aspecte de design, prin CSS (nu mai e nevoie sa setezi float-left-uri ca la balamuc pentru div-urile astea, si nu-ti vor mai “sari” din rand din cauza continutului)
2. folosind abordarea cu DIV-uri poti implementa apoi lejer tot felul de minunatii drag&drop din familia AJAX.
O lista completa a proprietatilor CSS din familia TABLE-lor gasesti aici:
TABLE { display: table }
TR { display: table-row }
THEAD { display: table-header-group }
TBODY { display: table-row-group }
TFOOT { display: table-footer-group }
COL { display: table-column }
COLGROUP { display: table-column-group }
TD, TH { display: table-cell }
CAPTION { display: table-caption }
Pentru o documentare completa, mergi aici.
Pe vremea tabelelor era relativ usor sa obtii un layout centrat relativ in pagina: faceai un tabel cu un rand si o celula, setai celula respectiva sa fie aliniata centrat si pe orizontala si pe verticala, si in ea mai bagai un al doilea tabel in care faceai apoi varza cu carne. Usor si frumos. Dar treaba asta niciodata nu mergea in NS, pentru simplul motiv ca NS accepta 100% ca inaltime doar pentru primul nivel de tabelare. De la al doi-lea nivel de tabelare in jos NS o ia razna cu totul in ceea ce priveste inaltimea tabelelor. Ma rog, asta se intampla pe vremea cand maai existau oameni care sa foloseasca NS, si cand se facea caz pe seama lor. Not anymore.
Dar problema ramane. De ce? Pentru ca alinierea pe verticala este o proprietate specifica NUMAI anumitor elemente HTML. DIV-ul NU e unul din ele. Ce te faci atunci?
Pai… depinde. Ai nu una ci doua solutii, in functie daca vrei ca div-ul tau sa aiba inaltime fixa sau relativa la inaltimea paginii. Indiferent cum vine cazul, principiul de baza e ca div-ul cu pricina trebuie sa-l bagi intr-un context clar definit ca position, indiferent ca e relative sau absolute. Sa le luam pe rand…
1. DIV centrat vertical in pagina, cu inaltime relativa la inaltimea paginii.…
cam simplu 🙂 Se seteaza div-ul din css, cu urmatorii parametri:
position: absolute; height: x%; top: ((100-x)/2)%;

Bine, ce am scris eu aici e un EXEMPLU, fratilor. NU incerca asa ceva acasa, ca n-o sa mearga. Ca sa vezi cam cum ar arata ceva de genul asta in rea-l live, uite un exemplu mai exemplificator:
position: absolute; height: 40%; top: 30%;
Daca ai nelamuriri, baga un comentariu si le lamurim.
2. DIV centrat vertical in pagina, cu inaltime fixa.
Asta poate sa para mai tricky… dar e rezolvabil. Inainte de toate, cream un DIV “dummy”, pe care-l definim in modul urmator:
.dummy {position: absolute; top: 50%;}
Div-ul asta, in mod clar, va sta (va avea originea) exact la mijlocul verticalei paginii. Pasul doi este sa cream in interiorul lui dummy DIV-ul care ne intereseaza pe noi, si care sa zicem ca vrem sa aiba inaltimea X. Parametrii lui in CSS vor arata asa:
position: absolute; height: Xpx; top: (-X/2)px;

Repet, pentru ca mai sus: asta e un exemplu de tip formula. Acelasi lucru, exemplificat mai concret, ar arata cam asa:
position: absolute; height: 300px; top: -150px;
Problema rezolvata!
Nota 1: Pentru cine nu intelege cum merge treaba cu position:absolute si cam ce presupune aceeasi treaba, recomand cu caldura articolul Elemente pozitionate ABSOLUTE in context RELATIVE.
Nota 2: Pentru cine se loveste de probleme legate de alinierea pe orizontala sau de width, ia cu paine de-aici: DIV-uri centrate in pagina: atentie la MARGIN.
Nota finala: Parametrii pe care i-am dat in exemplele de mai sus reprezinta STRICTUL NECESAR functionarii trebii respective. Evident ca esti liber sa adaugi de la tine orice si oricati parametri suplimentari vrei, pornind de la banalul width si mergand pana la cele mai rele hackuri CSS pe care le stii tu. Evident, restul nu ma mai priveste si e treaba ta. 🙂
Ca sa lamurim de la (destul de) inceput de ce ma tot agit atata cu DIV-urile, si nu folosesc in schimb TABLE: este vorba de modul de incarcare a paginii, in primul rand.
Un TABLE este compus in TR-uri, compuse la randul lor din TD/TH-uri. Problema este ca IE nu poate afisa un TABLE pana cand nu a terminat de incarcat TOT continutul lui. Cu alte cuvinte, daca graffiti de pilda ar fi facut tot dintr-un singur TABLE, atunci ai sta si te-ai uita la o pagina goala, cum se tot incarca fara sa afiseze nimic, si abia la sfarsitul incarcarii s-ar afisa totul, brusc. Acum, sa fim seriosi, graffiti poate nu e cel mai bun exemplu… Du-te pe engadget.com de pilda, si vezi acolo batalie cu bandwidth-ul… Daca un site ca ala ar fi facut cu tabele, ar fi JALE.
In timp baietii de la M$ s-au gandit sa mai rezolve un pic din problema, permitand, in anumite conditii, ca afisarea sa se faca rand-cu-rand… dar tot cam degeaba – fiecare rand trebuie sa isi incarce intreg continutul inainte de a fi afisat. Crappy. Real crappy.
DIV-urile in schimb, ca sa poata fi afisate, nu au nevoie de CONTINUT, ci doar de STRUCTURA.
Asta, plus eleganta CSS-ului, ma fac un fan declarat al DIV-urilor, sau, ma rog, al modalitatilor alternative de a “taia” un layout.
Pana sa ma lamuresc de niste lucruri, am tras de google de-am ametit… De ce? Pentru ca vroiam si eu, ca tot omul, sa centrez un DIV in pagina. IE, asa simplu la minte cum e el, ma asculta orbeste… Dar FF, cu pretentiile lui puriste, nu vroia neam! Asta pana am aflat de ce.
Browserele mai normale la cap (FF included) nu iau lucrurile “de bune”. Nu gandesc prieteneste, ci matematic. Ca sa pozitionezi un element in termeni relativi, browserul trebuie sa stie exact care sunt parametrii necesari calculului acelei pozitii relative. Cum, in cazul asta, vorbim de pozitionare pe orizontala, browserul are nevoie sa stie care sunt MARGIN la stanga si la dreapta. Cu alte cuvinte, daca vreau un DIV centrat pe mijlocul paginii, e musai sa-i dau
margin-left: auto;
margin-right: auto;
Fara setarile astea, FF o sa se incapataneze sa pozitioneze orice DIV (care nu are float) la marginea din stanga a holderului (parintelui etc.) sau, indiferent de text-align-ul acelui holder.
Astea fiind zise, am cam rezolvat problema! Prea simplu? Nu conteaza, sper doar sa-ti foloseasca.
Pentru cine a folosit GIF-uri si stie cat de pacatoasa e transparenta lor pe la margini, PNG-ul, cu nivelele lui de transparenta atat de dragalashe, e mana cereasca. Numai ca IE (inclusiv v.7) (ca de obicei) e atat de inapoiat incat nu poate afisa zonele transparente din PNG-uri ca transparente, ci ca un background gri, suparator. Daca chiar vrei sa obtii PNG cu transparenta in IE, trebuie musai sa bagi un filtru (filtrul = o alta inventie abominabila M$) dedicat trebii asteia, filtru care nu face decat sa afiseze, ca background, imaginea PNG setata, dupa exemplul:
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src=img/png-file.png);
Solutia cea mai folosita de catre trupetzi in general e sa implementezi un javascript care, odata incarcata pagina, sa “caute” prin toata structura HTML dupa imagini de tip PNG si sa le inlocuiasca, cu un replace global, cu holdere in care sa introduca filtrul respectiv, preluand, evident, de la imaginile originale toti parametrii necesari afisarii corecte (latime, inaltime, url imagine). Cum solutia asta este una care tine de javascript, si cum presupune operatii asupra structurii documentului, o las aici, si continui cu ce ma intereseaza pe mine aici: aspectul CSS al problemei.
De ce CSS? Poi e cam simplu… pentru ca de multe ori ai nevoie sa folosesti acel PNG in CSS, ca background-image… caz in care solutia de mai sus devine complet ineficienta.
Pentru cine nu a cetit inca articolul !important; , recomand inainte de a continua, lectura lui.
In mod normal, in CSS, definim o imagine ca background in felul urmator:
.style {
background-image: url(img/png-file.png);
}
, treabã care merge bine in FF dar nu merge deloc in IE.
In IE in schimb, dupa cum ziceam, poti face asa:
.style {
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src=img/png-file.png);
}
Dupa cum vezi, rezulta doua proprietati diferite, care incearca sa obtina acelasi lucru. Daca ai cetit deja articolul recomandat mai sus, atunci o sa intelegi de ce solutia la problema noastra e sa aplicam un dublu !important; , in felul urmator:
.style {
background-image: url(img/png-file.png) !important;
background-image: none;
filter: none !important;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src=img/png-file.png);
}
In felul asta, FF o sa “vada” un background si zero filtre, iar IE o sa “vada” zero background si un filtru. Problema rezolvata. Atat pentru azi…
Exista tot felul de proprietati si functionalitati CSS si nu numai, extrem de utile uneori, frumos implementate in FF dar deloc sau prost implementate in batranul (a se citi “decrepitul”) IE:
PNG-uri cu transparenta, transparente pur si simplu, scriere pe mai multe coloane, latimi si inaltimi minime si maxime etc.
Azi ma opresc la cele din urma, latimile si inaltimile maxime / minime.
In FF exista, foarte simplu, proprietati CSS pentru asta: max-width, min-height etc. In IE? uhhhh… nada.
Mare (?) noroc ca, de la IE 5.0 in sus, a fost implementata o chestie noua: suportul pentru expresii in CSS. Evident, nici un alt browser nu le “intelege”, si nici macar nu sunt un standard universal, asa ca expresiile astea dragute nu trec de validarile clasice. Dar, pentru cine e dispus sa renunte la validari, iata cum pot obtine un max-height de pilda, functional si in IE si in FF:
.class {
overflow:auto;
max-height: 100px;
*height:expression((this.scrollHeight > 75) ? “100px” : “auto” );
}
Observi ca am definit intai max-height in asa fel incat sa-l inteleaga FF-ul, dupa care am folosit un hack-ul cu “*” (un browser senil ca IE trece peste steluta aia, nu se incurca in ea, chiar daca ar putea fi o potentiala eroare… un browser sanatos la cap ignora complet acea definitie. In felul asta, se pot face uneori distinctii in definirea unor proprietati, de la browser la browser).
Restul se cam explica de la sine… E o expresie conditionala clasica de la care poti extrapola, daca vrei sa o adaptezi nevoilor tale.
Nota: nu recomand folosirea expresiilor. Doar IE le “vede”, restul browserelor nu. Dar, cum ATATA lume se plange de min-width si de altele asemenea lui, m-am gandit sa-i ajut un pic cu acest mic hack.
Pentru cei care nu stiu inca, exista un mic “hack” CSS care, folosit corect, nu numai ca trece de validarile clasice, dar e si foarte util. E vorba de !important;.
Cum se foloseste: in loc de width: 300px; se poate scrie width: 300px !important;. De ce si la ce foloseste? Vedem mai jos…
Functia de baza a lui !important; este de a prioritiza/ierarhiza proprietatile CSS atasate unei pagini (fie ca sunt inline sau raspandite in fisiere css externe). Din perspectiva asta, el poate fi folosit in 2 scopuri principale:
1. Primul scop, mai cunoscut si raspandit, este de a diferentia anumite proprietati in FF fatza de IE. In cazul asta, hackul se bazeaza pe faptul ca, acolo unde gaseste aceeasi proprietate de 2 ori, IE tinde sa prefere/sa ia un calcul proprietatea care nu are !important; atasat la sfarsitul ei.
Exemplu:
Sa spunem ca vrem ca un element sa aiba in IE width: 100px; iar in FF 120px; Cum facem? Simplu: scriem aceeasi proprietate de 2 ori: width: 120px !important; width: 100px;. FF va intelege din asta 120px, iar IE va intelege 100px. Simplu, la obiect si foarte util in multe cazuri.
2. Al doilea, mai putin cunoscut dar la fel de important, este de a prioritiza o proprietate pe scara ierarhica. Ce inseamna asta?
A. Stim (sau aflam) ca in CSS se pot defini Clase sau Tag-uri. Clasele sunt cazuri particulare si se prefixeaza cu un punct, iar tag-urile sunt practic redefiniri globale ale modului de afisare a tagurilor HTML. body {} redefineste un TAG, iar .body {} este o CLASA.
Ce retinem de aici e ca proprietatile unul TAG sunt superioare ierarhic proprietatilor unei clase. Daca de pilda definesc p {color: #cccccc;} si apoi in cadrul unui P vreau sa folosesc clasa .green {color: #009900;}, .green va apare gri in loc de verde, pentru ca un tag e mai general/global decat o clasa, adica P este mai general/global decat .green.
B. Mai stim (sau aflam) ca in CSS putem defini clase complexe. De pilda, .green {} e una, .green .title {} inseamna “toate title-urile care se gasesc intr-un green“. Asta ne poate ajuta sa ierarhizam, sa detaliem si sa prioritizam foarte bine si ordonat o multitudine de clase si de cazuri particulare.
Ca sa revenim la oile noastre: concluzia din paragrafele A si B e ca in CSS ierarhia exista si e importanta.
Dar ce faci cand vrei sa faci override la ierarhie? Bagi un !important;.
Problema de mai devreme, cea cu p si .green, se rezolva asa: .green {color: #009900 !important;}. In felul asta, daca folosim un .green intr-un p, proprietatea color din .green va deveni mai importanta ierarhic si se va afisa ca atare.
Uneori, ca si in cazul butoanelor bogate grafic dar editabile ca text, e nevoie sa poti folosi un element html pozitionat ABSOLUT intr-un context RELATIV.
Este vorba despre proprietatea CSS “position” care poate lua una din cele 4 valori: absolute / relative / fixed / static. O sa las aici deoparte valorile fixed si static, si-o sa ma concentrez un pic asupra celor care ne intereseaza aici: relative si absolute.
In imaginea din stanga, pe care o folosesc ca exemplu, chenarul albastru resprezinta elementul parinte (contextul), chenarul rosu este un element pozitionat absolut, iar cel verde este un element pozitionat relativ. Elementele rosu si verde sunt incluse, evident, in cel albastru, ca si cod.
Relative – folosind proprietatea CSS position: relative; instruim browserul sa pozitioneze elementul in cauza relativ la contextul in care se afla acesta, in mod fluid. Cu alte cuvinte, fortam elementul relativ sa depinda, ca pozitionare, de tag-ul imediat superior lui DAR SI de curgerea in-line a elementelor din respectivul context. Cu alte cuvinte, sa se comporte, in termeni grosieri, ca o litera intr-un text.
Absolute – folosind proprietatea CSS position: absolute; instruim browserul sa pozitioneze elementul in cauza relativ la contextul in care se afla acesta, dar independent de curgerea in-line a celorlalte elemente din context. Cu alte cuvinte, fortam elementul relativ sa isi mentina coordonate de pozitionare fixe, exprimate in pixeli sau directii.
Cel putin in teorie.
Pentru ca, atunci cand incerci sa faci asta in practica, observi ca IE si FF o iau razna cand folosesti position:absolute, fiecare interpretand diferit LA CINE se face raportarea in pozitionare. Si acelasi element pozitionat absolut va fi afisat complet diferit in diferitele browsere.
DE CE? Pentru ca diferite browsere decid diferit daca raportarea se face la elementul html imediat superior ierarhic (parent tag) sau la BODY.
Pare absurd, stiu. Dar totul are o explicatie. Atunci cand trebuie sa pozitioneze un element ABSOLUTE, toate browserele “cauta” in sus, ierarhic, urmatorul element HTML definit ca RELATIVE. Unele considera ca acesta e parent-ul, altele ca acesta ar fi body. De aici si diferenta de prelucrare vizuala.
Rezolvarea? 🙂 e simpla: Chiar daca pare redundant, atunci cand vrei sa-l pozitionezi pe X absolut in Y, atunci defineste-l pe Y ca avand position: relative;.
Asta va forta orice browser sa inteleaga EXPLICIT la cine se face raportarea (urmatorul element superior ierarhic care este relative fiind in mod explicit definit), si sa rezolve vizual problema la fel, indiferent daca vorbim de FF, IE sau orice alt program contemporan.
De multe ori se poate intampla sa ai nevoie de un buton mai bogat grafic (sa tipe Photoshopu’ din el) dar nu vrei ca la fiecare cerere a clientului sa trebuiasca sa refaci GIF-ul sau JPG-ul respectiv.
Presupunand ca fontul este unul din seria celor folosibile pe web, treaba asta e rezolvabila. Cum?
Folosind doua tag-uri atunci cand definim elementul respectiv, fiecare cu cate un background definit din CSS pe el.
De ce doua? Pentru ca unul sa se ocupe de 2 laturi, iar celalalt de celelalte 2 laturi ale formei (in general dreptunghice) a butonului nostru.
In exemplul dat de mine aici, A-ul ar avea ca background prima imagine, mai lunga (just in case, cine stie cat text o sa fie nevoie sa intre acolo), iar LI-ul ar avea ca background a doua imagine, fiecare cu alinierile date in exemplu.
Mai ai de setat doar niste padding-uri si niste margin-i, si esti gata!
Spor! (si astept comentarii / sugestii / intrebari)
Later edit:
In urma unui comentariu foarte pertinent, Vlad a observat ca abordand asa exemplul asta, partea din dreapta a butonului ramane descoperita, “fara focus”. Asa e.
Rezolvarea vine dintr-o simpla schimbare de background-uri in css: li-ul sa primeasca ca background prima imagine, aliniata left-top, iar A-ul pe a doua, aliniata right-top. In felul asta butonul nostru devine complet acoperit de focus.