blog.pauloasilva.com

CSS Only Tabbed Navigation

Toda a gente reconhece que a web está mais airosa com todo o poder que o JavaScript e um (não tão) novo paradigma assíncrono lhe confere. Isto tudo potenciado por browsers mais poderosos, com motores de JavaScript poderosíssimos e computadores, sejam eles portáteis ou de secretária, com processadores de fazer inveja a alguns servidores com meia dúzia de anos.

Embora um defensor acérrimo e contribuinte da filosofia/movimento opensource, não aceito que a solução seja simplesmente importar um plugin jQuery UI. Desde logo, porque acabamos por obrigar os utilizadores a descarregar mais dados, ficamos a lutar contra algumas limitações dos browsers (i.e. número de pedidos concorrentes) e por fim, mas não por último, porque a maioria desses plugins não tem em consideração questões de acessibilidade.

Lembro os mais distraídos que também o CSS tem evoluído e com apenas uma das novidades do CSS3, consegui uma solução de navegação por separadores, com um DOM muito limpo e poucas linhas de CSS.

DOM

<form action="http://dev.pauloasilva.com/css/tabs/" class="tabs">
	<ul class="ctrl">
		<li>
			<label for="tab1">Tab One</label>
		</li>
		<li>
			<label for="tab2">Tab Two</label>
		</li>
	</ul>
	<input type="radio" checked="checked" name="tab" id="tab1" />
	<div class="container">We are in the 1st tab</div>
 
	<input type="radio" name="tab" id="tab2" />
	<div class="container">We are in the 2nd tab</div>
</form>

CSS

form.tabs ul.ctrl li {
	display: inline-block;
	padding: 0 5px;
}
form.tabs ul.ctrl label {
	display: block;
	line-height: 40px;
	min-width: 75px;
	text-align: center;
}
form.tabs div.container, form.tabs input[type="radio"] {
	display: none;
}
form.tabs input[type="radio"]:checked + div.container {
	display: block;
}
form.tabs ul.ctrl li label {
	cursor: pointer;
}

A lógica assenta exclusivamente numa melhoria na acessibilidade/usabilidade dos formulários que, mediante a correcta utilização da tag <label>, transferem o click nesta para o campo (<input />) a que está implícita/explicitamente associada.

Neste caso as <label> estão associadas a radio buttons que no DOM estão imediatamente antes dum elemento <div> que contém o conteúdo da tab. Assim, deve existir um par <input type="radio" /> por cada tab e o mesmo [o par <input />, <div>] deve encontrar-se no DOM na mesma ordem da tab.

O uso de radio buttons serve o propósito de ter apenas uma tab aberta/seleccionada em cada momento.

Depois é só brincar com o novo selector :checked.
Sempre que se carrega numa tab estamos na verdade a carregar num elemento <label> que transfere o evento click para o respectivo radio button. Se o estado deste for marcado (:checked) então, através do selector + alternamos a propriedade display do elemento <div> imediatamente a seguir (no DOM) de none para block, ficando o conteúdo do mesmo visível.

Obviamente, queremos algum estilo visual que confira aos controlos a tradicional estrutura de separadores.

Estilo

/* Style */
form.tabs div.container {
	border-top: 1px solid #D6D6D6;
	margin-top: -1px;
	padding-top: 10px;
}
form.tabs ul.ctrl li {
	border-color: #D6D6D6;
	border-style: solid;
	border-width: 1px;
}
form.tabs ul.ctrl li.on{border-bottom:1px solid #FFFFFF}

Há uma classe .on que quando aplicada a uma elemento <li> simula o efeito do separador seleccionado, no entanto esta solução, livre de JavaScript, não permite adicionar e remover essa classe.
Assim, para que tudo funcione para todos, podemos adicionar o JavaScript necessário para o efeito no evento onclick da <li>.

Com esta solução consigo dormir quase descansado. E digo “quase” porque embora seja acessível mesmo quando não existe suporte para JavaScript, apresenta erros de validação WCAG v2 A.

Para começar 2012 em cheio, deixo ainda um protótipo funcional deste controlo.

Deixar uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

*

five + = 12

Pode usar estas etiquetas HTML e atributos: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">