Butoane (si/sau tab-uri) bogate grafic dar editabile ca text (optimizate + acum cu roll-over)

Scriam acum ceva vreme despre posibilitatea de a crea butoane bogate grafic dar editabile ca text.

Prima problema cu abordarea respectiva era una de optimizare: pentru acelasi buton trebuiau folosite 2 imagini, deci 2 requesturi diferite pe server. In timp, si pe un server mai aglomerat, orice problema de genul asta incepe sa se faca simtita si sa se ceara optimizata.

A doua problema: pe langa asta, m-am mai lovit de o problema: lipsa unui efect la roll-over.

Treaba asta m-a facut sa re-gandesc un pic abordarea intregii chestii, in felul urmator:

1. Inainte foloseam 2 tag-uri, unul in altul, sub forma:

A)
<li>
  <a>buton aici</a>
</li>

Noua abordare foloseste tot 2 tag-uri, doar ca de data asta un pic diferit:

B)
<a>buton aici<div class=end></div></a>

Noul DIV, marcat cu clasa “end”, are rolul de a defini, grafic, partea din dreapta a butonului. O sa introduc aici o schema explicativa, dupa care o sa continui cu explicatiile mai jos:

Dupa cum se vede in imaginea de mai sus, in loc sa folosim mai multe imagini, vom folosi o singura imagine, suficient de lunga incat sa acopere orice scenariu* si avand inaltimea dubla: un rand pentru starea normala si unul pentru starea de “over”.

* Pentru a preveni depasirea latimii maxime a unui asfel de element se poate folosi oricand combinatia impreuna a urmatoarelor trei proprietati css:
1. max-width pentru a limita latimea butonului la maximul impus aici;
2. white-space: nowrap; pentru a preveni “ruperea” textului pe mai multe randuri;
3. overflow: hidden; pentru a “ascunde” orice text care ar depasi limitele impuse la punctul 1.

Pornind de la premisa ca pentru acest buton/tab vom folosi codul de mai sus ( B) ), hai sa studiem un pic cum vom obtine efectul dorit, pornind de la dimensiunile prezentate in imagine:

1. Paddingul aparent:

a {
padding-top: 8px;
padding-bottom: 5px;
padding-left: 16px;
padding-right: 16px;
}

Dar, daca ne uitam atent, vedem ca in dreapta o parte din “padding” este furata de fapt de DIV-ul “end”. Asa ca vom rescrie un pic regulile de padding pentru a lasa 6 pixeli liberi in dreapta pentru “end”:

a {
padding-top: 8px;
padding-bottom: 5px;
padding-left: 16px;
padding-right: 10px;
}

Nota: pentru ca elementul nostru (<a>) sa se comporte asemeni unui “box” (sa poata accepta proprietati ca “height”, de pilda), mai trebuie un mic artificiu: sa-l declaram ca “block” si sa-i setam un “floating”:

a {
display: block;
float: left;
height: 10px;
}

2. Pozitionarea elementelor
Pentru a putea pozitiona cu precizie (in mod “absolut”) DIV-ul “end”, va trebui ca parintele lui (in acest caz, <a>) sa fie pozitionat “relativ”:

a {
position: relative;
}

iar pe “end” sa-l pozitionam “relativ”:

a .end {
position: absolute;
}

Pentru a “rezerva” apoi spatiul din dreapta necesar afisarii lui “end”, vom adauga o margine in dreapta lui <a>:

a {
margin-right: 6px;
}

si il vom pozitiona absolut pe “end”:

a .end {
right: 0px;
top: 0px;
}

Dar asta ar face ca “end” sa fie afisat in interiorul lui <a>, nu in exterior asa cum ne dorim de fapt. Ca sa-l facem sa se afiseze in exterior il vom “forta” sa fie afisat mai la dreapta, folosind un margin negativ in dreapta lui:

a .end {
margin-right: -6px;
}

In momentul acesta putem sa mai setam cateva proprietati necesare afisarii corecte a celor 2 elemente impreuna, proprietati legate de dimensiunile acestora:

3. Dimensiuni

<a> trebuie sa aiba setata doar inaltimea (tineti minte, intreaga idee e ca latimea lui sa poata varia). Formula de calcul a inaltimii reale este:

IR = IA – P

unde :
IR = inaltimea reala;
IA = inaltimea aparenta;
P = paddingul insumat (top + bottom);

In cazul nostru, rezulta:

IR = IA – P = 23 – 8 – 5 = 10, deci

a {
height: 10px;
}

Cum “end” e doar un element decorativ, fara padding, atunci e foarte usor sa setam inaltimea si latimea lui:

a .end {
height: 23px;
width: 6px;
}

4. Background-urile

Intreaga ideea a tutorialului este de a folosi o singura imagine pentru a obtine toate efectele astea. Asa ca hai sa definim background-urile:

a, a .end {
background-image: url("tab_back.gif");
}
a {background-position: left 0px;}
a .end {background-position: right 0px;}

daca nu e clar inca: primul parametru se refera la alinierea pe orizontala (left / right) iar al doilea la cea pe verticala, in cazul nostru “0px” echivaland cu “top”.


Pana aici avem urmatorul CSS rezultat:

a, a .end {
background-image: url("tab_back.gif");
}

a {
height: 10px;
padding-top: 8px;
padding-bottom: 5px;
padding-left: 16px;
padding-right: 10px;
margin-right: 6px;
display: block;
float: left;
height: 10px;
position: relative;
background-position: left 0px;
}

a .end {
height: 23px;
width: 6px;
margin-right: -6px;
right: 0px;
top: 0px;
position: absolute;
background-position: right 0px;
}

Sa continuam cu effectul de roll-over…

Din imaginea prezentata la inceputul tutorialului ne putem da seama ca pentru a obtine un efect de roll-over e suficient sa “instruim” backgroundurile celor 2 elemente ca, la roll-over, sa se afiseze shiftat in sus, dand in felul acesta efectul dorit. Shiftat cu cat? cu echivalentul IA (inaltimii aparente), care era de 23px in cazul nostru. Asadar:

a:hover {
background-position: left -23px;
}
a:hover .end {
background-position: right -23px;
}

Ovservam ca nu am folosit .end:hover ci a:hover .end. De ce? Pentru ca nu vrem ca “end” sa reactioneze la :hover independent, vrem ca el sa se comporte ca atare numai atunci cand parintele lui o face. Folosind sintaxa de mai sus, ne asiguram de lucrul acesta.

Cam asta ar fi. Spor la codat! 🙂


Note:
1. Daca vreti sa folositi efectul de :hover si pe alte elemente decat pe cele care-l accepta in mod natural (div-uri etc), atunci dati un ochi aici ca sa vedeti cum puteti obtine asta.
2. Uneori se doreste ca, acolo unde avem mai multe TAB-uri/Butoane, cel selectat sa fie vizibil ca atare. Solutia preferata de mine este sa marchez elementul selectat cu o clasa (suplimentara), ceva in genul:

<a class=selected>buton aici<div class=end></div></a>

treaba insotita in CSS de urmatoarea completare:

a:hover, a.selected {
background-position: left -23px;
}
a:hover .end, a.selected .end {
background-position: right -23px;
}

Previous Post

Comments are closed.

Comments (3)

  1. aha…

    retete de sarmale n-ai? 😛

  2. e clar, meritzi concediu cu plata 😛
    acu serios, ingenioasa abordare 😉

  3. Petru

    Thanks!

    Promit sa si citesc in curand tot ce ai zis tu mai sus. 🙂

    P.