Quando, un po’ di tempo fa, ho letto un articolo di Alex Griffioen relativo a come rendere “sexy” dei semplici link con l’utilizzo di poco CSS mi sono entusiasmato.
No, non mi sono entusiasmato per poche righe di CSS, ma perché mi è venuta una buona idea. Poco tempo prima avevo letto un articolo di Aaron Gustafson relativo alla libertà che i <button /> portano rispetto ai <input type="button" />.

Facendo quindi due più due ho pensato di unire assieme le due cose e costruire un modello semplice di bottoni e ancore (<a>).

nButtons

Questo piccolo lavoro nasce quindi con l’intenzione di ampliare il codice di Alex Griffioen, dal quale evidentemente ho presto spunto, e dato che tale articolo si occupava di ancore io ho chiamato questo mio esperimento nButtons (ovvero “and buttons”).

In teoria le tecniche utilizzate dovrebbero essere le stesse, nella pratica non è così: i <button> a differenza delle <a> (o di qualsiasi altro tag con stile display:block;) non sono così malleabili da permettere un pieno controllo; in IE e Opera ad esempio quando l’utente clicca il button si sposta (per simulare un bottone premuto) mentre invece in Firefox e Safari no; il problema reale è però rappresentato dai margini, applicati in maniera differente dai singoli browser.


Osservando cosa succede con il codice più semplice già ci si rende conto di qualche discrepanza, ma non completamente

Gli stili

.nbuttons a img, .nbuttons button img {
	border:0;
	margin:0 4px -4px 0;
}

I bottoni

<div class="nbuttons">
	<a href="#"><span>
		<img src="accept.gif" alt="" />anchor
	</span></a>
	<button type="submit"><span>
		<img src="accept.gif" alt="" />button
	</span></button>
</div>

In pratica gli oggetti <button>, anche se impostati con margin:0;, posseggono dei margini speciali che complicano la vita sia nell’applicazione della tecnica sliding doors sia nell’allineamento verticale con nbuttons costituiti da <button>.


Tutto ciò che ci serve per cominciare sono 3 immagini: una (opzionale) per l’icona del bottone, una per il background dell’<a>/<button> e una per il background dello <span> (click destro “salva con nome” per salvarle sul vostro computer).

Applicando quindi il codice utilizzato nell’articolo “sexy buttons” anche ai <button> il risultato sembra essere disastroso

CSS Fase 0

.nbuttons { /* Generic container for floating nButtons */
	margin:5px 0;
	overflow: hidden;
	height:40px;
	width:100%;
	clear:both;
}
 
.nbuttons a img, .nbuttons button img { /* nButtons' images */
	border:0;
	margin:0 4px -4px 0;
}
 
.nbuttons a, .nbuttons a:hover, .nbuttons a:link,
.nbuttons a:active, .nbuttons button { /* nButtons' fonts */
	text-decoration:none;
	color:#DDD;
	outline:none; /* hide dotted outline in Firefox */
}
 
.nbuttons a, .nbuttons button {
	display:block;
	float:left;
	overflow:visible;
	cursor:pointer;
	border:0;
	margin:0;
	padding:0;
	background: url('bg_button_a.gif') no-repeat right 0px transparent;
	padding-right: 18px; /* sliding doors padding */
}
 
.nbuttons a span, .nbuttons button span {
	display:block;
	background:url('bg_button_span.gif') no-repeat left 0px transparent;
	padding:12px 5px 10px 18px;
	font-size:12px;
	font-family:helvetica,arial,serif;
	font-weight:bold;
}

Ecco l’esempio live


Il motivo di questo scempio sta proprio in questi margini aggiuntivi:
nessun margine per Opera e Safari
1px top, bottom e 3px left, right per Firefox
2px top e bottom per Internet Explorer.

Eliminando questi margini aggiuntivi (con semplici margini negativi via css) il risultato non è un gran che. Su Firefox funziona ma negli altri browser quando si clicca sul bottone le due immagini di sfondo si muovono in maniera differente: un incubo.

Per ovviare a queste incongruenze fra i browser e fare in maniera che il <button> risultasse assolutamente identico a una <a> ho aggiunto così due <span>, invece che uno, facendo svolgere allo span più esterno (class=”a”) la funzione (stilisticamente parlando) che nel codice originale era svolto dai <button> stessi.

Il risultato con un css, leggermente modificato, funziona bene

CSS Fase 1

.nbuttons { /* Generic container for floating nButtons */
	margin:5px 0;
	overflow: hidden;
	height:40px;
	width:100%;
	clear:both;
}
 
.nbuttons a img, .nbuttons button img { /* nButtons' images */
	border:0;
	margin:0 4px -4px 0;
}
 
.nbuttons a, .nbuttons a:hover, .nbuttons a:link,
.nbuttons a:active, .nbuttons button { /* nButtons' fonts */
	text-decoration:none;
	color:#DDD;
	outline:none; /* hide dotted outline in Firefox */
}
 
.nbuttons a, .nbuttons button span.a {
	display: block;
	background: url('bg_button_a.gif') no-repeat right 0px transparent;
	padding-right: 18px; /* sliding doors padding */
}
 
.nbuttons a span, .nbuttons button span.b {
	display:block;
	background:url('bg_button_span.gif') no-repeat left 0px transparent;
	padding:12px 5px 10px 18px;
	font-size:12px;
	font-family:helvetica,arial,serif;
	font-weight:bold;
}
.nbuttons a, .nbuttons button {
	float:left;
	overflow:visible;
}
.nbuttons button {
	display:block;
	cursor:pointer;
	border:0;
	margin:0;
	padding:0;
	background-color:transparent;
}

HTML Fase 1

<div class="nbuttons">
	<a href="#"><span>
	<img src="accept.gif" alt="" />anchor
	</span></a>
	<button type="submit">
	<span class="a"><span class="b">
	<img src="accept.gif" alt="" />button
	</span></span></button>
</div>

Inevitabilmente rimangono incongruenze (anche se minimali) fra Firefox/IE e Opera/Safari. Si rende necessario eliminare quindi i margini “speciali” con dei margini negativi, applicando le regole però solo a Firefox e IE indipendentemente.


Aggiungendo quindi un po’ di css si impostano i margini negativi, gli stili per l’hover e il click (active), e con onclick="this.blur();" si evita che i bottoni rimangano attivi dopo il click. L’esempio spiega meglio l’effetto.

CSS Fase 2

.nbuttons button[type] {
	margin:-1px -3px; /* FIREFOX */
	/* margin:0; /* SAFARI / OPERA */
}
* html .nbuttons button {
	margin:-2px 0; /* IE6 */
}
 
.nbuttons a:hover, .nbuttons button:hover span.a  {
	background-position:right -40px;
	color:#FFF;
}
.nbuttons a:hover span , .nbuttons button:hover span.b  {
	background-position:left -40px;
} 
.nbuttons a:active, .nbuttons button:active span.a {
	background-position:right -80px;
}
 
.nbuttons a:active span, .nbuttons button:active span.b {
	background-position:left -80px;
}

Come si può notare però la scelta è se lasciare disallineati i bottoni in firefox o in safari/opera.
Per ovviare a questa impossibile scelta (anche se il problema è minimale) si può optare per la via dei “CSS hacks”.
Mi preme sottolineare che non sono un fan dei “CSS hacks”, in questo caso però non compromettono la validazione del codice quindi, con la dovuta attenzione, li sfrutto.

Il risultato finale è l’assoluta corrispondenza fra i vari browser e tutto quello che serve è l’aggiunta di qualche riga css che non viene interpretata da firefox o ie:

Hack per Opera e Safari (Fase 3)

@media all and (min-width: 0px)  {
.nbuttons button[type] {
	margin:0; /* OPERA + SAFARI */
}
}

Come cambiare lo stile dei bottoni? Basta scambiare le immagini di sfondo come in questo esempio.
Ovviamente se doveste cambiare le dimensioni sarà necessario ricalcolare larghezze, altezze e padding (ricordando che l’altezza complessiva è la somma di “height”+”padding-top”+”padding-bottom” e che la larghezza complessiva è la somma di “width”+”padding-left”+”padding-right”).


Enjoy Sexy Anchors’n'Buttons…