Css Orientado a Objetos

Css Orientado a Objetos?

E por que não ?

Eu sei, orientação à objetos é um paradigma de programação, sei também que Css não é uma linguagem de programação.

Mas nós podemos usar alguns conceitos desse paradigma tão usado e usá-lo ao nosso benefício, mesmo com uma linguagem de formatação.

A orientação à objetos nos ajuda a abstrair a complexidade de uma aplicação de forma coesa e organizada, usando conceitos
que temos em nossa mente para descrever de maneira bem clara o funcionamento de um conjunto ou sistema, de forma mais humana,
podemos modelar o código para atender aos requisitos necessários para seu funcionamento adequado.

A idéia de Orientação à Objetos é muito boa, o fato do Css não ter todos os requisitos para ser uma linguagem orientada à objetos,
não significa que não possamos usar alguns conceitos de Orientação à Objetos. Quais conceitos?

– Abstração
– Encapsulamento
– Classe
– Herança
– Reuso de código

Como utilizar estes conceitos voltados para o Css?

Abstração

Abstração não é um conceito exclusivo de OO, porém é um deles.
Antes de solucionar um problema, precisamos visualizá-lo em nossa mente e tentar simplificá-lo de forma bem primitiva a fim de
tornar sua solução fácil também, é aqui que tudo começa. Vamos então gerar um problema hipotético e conveniente:

Problema: Implementação de uma caixa com todas as bordas arredondadas .

Great! Temos um problema.

Existem várias formas de se resolver um problema, principalmente um problema clássico como este, mas visualizar o
problema e definir as principais propriedades da solução é a parte mais importante. A implementação da solução é pessoal, tendo seus prós e contras.
Deixa a abstração deste problema para depois.

Encapsulamento

No Css, podemos definir a formatação de um elemento de acordo com o seu elemento pai. Ex:

.caixa p{ border:1px solid red }

Com isso podemos “encapsular” estes comportamentos dentro de um elemento pai, ou seja, só seus filhos terão estes comportamentos.

Classe e Objetos

NOsso problema pede uma caixa com bordas arredondadas, certo?

Existem vários tipos de caixas, então podemos pensar que essa caixa é de um tipo, do tipo com bordas arredondadas.

Bom, estamos aqui usando o conceito de classe, dando um tipo para um elemento. Logo a instância ou o objeto deste tipo seria cada implementação do seu html =).

Lembra da abstração? Então, visualize tudo na sua cabeça a partir de agora.

A minha solução para as bordas arredondadas é a seguinte:

Usei uma caixa maior, dentro dela utilizei 3 retângulos de mesma largura da caixa maior porém com altura pequena, empilhados um em cima do outro.

Um dos retângulos é o “header” digamos assim. Ele abrigará duas outras caixas menores, uma flutuada à esquerda e outra à direita. Estas caixas menores serão responsáveis
por exibir as imagens de bordas arredondadas.

O segundo retângulo, é o do meio da pilha, ele abrigará de fato o conteúdo da caixa maior. Sua altura não é definida, ele cresce em altura de acordo com o tamanho do seu conteúdo.

Já o terceiro retângulo é uma réplica do “header” ele será um “footer” desta caixa e será exatamente igual ao primeiro retângulo.

A idéia é fazer com que o conteúdo do segundo retângulo empurre para baixo as bordas arredondadas inferiores, já que não sabemos qual será o tamanho da caixa em cada aplicação.

Ótimo, mas vamos ver um pouco de prática né ?

Ok, criei então um tipo para esta caixa, o tipo “rounded” ( Arredondado em inglês ), prefiri seu nome em inglês por ser menor.

Esta “Classe” ficou assim:

.rounded .r-header,
.rounded .r-footer,
.rounded .r-content,
.rounded .borders,
.rounded { display:block }

.rounded .r-header, 
.rounded .r-footer{ background-repeat:repeat-x }		

.rounded .borders{ line-height:0 }

.rounded .top-left, 
.rounded .bottom-left{ 
	float:left; 
	background:left no-repeat
}

.rounded .top-right, 
.rounded .bottom-right{ 
	float:right; 
	background:right no-repeat 
}               

Perceba que para esta solução, os dois retângulos que abrigam as imagens das bordas tem o mesmo comportamento, então otimizei ao máximo o Css para os comportamentos iguais.

A Classe “borders” se refere aos elementos de borda dentro dos retângulos, todos os 4 elementos de borda tem esta classe, e todos com comportamentos iguais.

Tudo foi definido apenas por classe, porque eu queria que não ficasse preso a apenas tipo de elemento html e para não ser necessário mexer no Css para funcionar com outros elementos.

Bom, então essa “Classe” seria nossa abstração para o tipo borda arredondada. Agora é onde chegamos na parte mais interessante sobre este post, onde utilizamos os dois últimos conceitos de OO, Reuso de código e Herança.

Já resolvemos o problema de bordas arredondadas, não precisamos resolvê-lo de novo, essa é uma das coisas interessantes quando pensamos em OO.

Eu queria fazer uma caixa com uma faixa cinza no topo e na parte inferior, que lembra uma janela do Mac. ( Eu disse “Lembra” )
Mas a janela do Mac é toda bonitinha, e tem os 4 cantos arredondados. Ótimo, então agora eu faço um objeto novo, ou melhor, uma classe nova, uma caixa arredondada do estilo Mac, ou seja, uma caixa do tipo arredondada do tipo mac.

Agora usamos o reuso de código, atráves de uma simples herança, usando a abstração da classe “rounded” com atributos encapsulados, para gerar uma nova caixa de novo tipo:

/*
 * @author Eduardo Ottaviani
 * @require {rounded.css}  
 */

.macboxgray .r-header{ background-image:url(../../img/back-top.png) }
.macboxgray .top-right{ background-image:url(../../img/right-top.gif) }
.macboxgray .top-left{ background-image:url(../../img/left-top.gif) }
.macboxgray .r-footer{ background-image:url(../../img/back-bottom.png) }
.macboxgray .bottom-left{ background-image:url(../../img/left-bottom.gif) }
.macboxgray .bottom-right{ background-image:url(../../img/right-bottom.gif) }

.macboxgray .borders{ 
	height:24px;  
	width:5px 
}
	
.macboxgray .r-header, 
.macboxgray .r-footer{ height:24px }

Da hora né? Olha quanta linha foi necessária para criar este novo objeto.
Você poderia estar se perguntando se não seria mais legível se eu nomeasse a classe assim:

.rounded.macboxgray

Seria, principalmente para ficar bem nítido e claro de quem a macboxgray herda, porém usar duas classes juntas não é uma boa idéia só por causa do ie6. Por que ?

Ao definir uma borda:

.rounded.macboxgray{ border:1px solid blue } 

No iE6, outro objeto que tem apenas a classe “rounded” também herdaria a borda azul =/ . No mínimo esquisito….

Para que você entenda como foi feita a herança, vou mostrar o html desta caixa:

<form class="macboxgray rounded">
	<span class="r-header">
		<span class="borders top-left"></span>
		<span class="borders top-right"></span>
	</span>
	
	<fieldset class="r-content">
		
		<p>								
		    lorem ipsum dolor amec lorem 
		    ipsum dolor amec lorem ipsum 
		    dolor amec lorem ipsum dolor amec 
			
		</p>
		
	</fieldset>
	
	<span class="r-footer">
		<span class="borders bottom-left"></span>
		<span class="borders bottom-right"></span>
	</span>	
</form>	

Olha ali, o nosso objeto é um form, do tipo macboxgray rounded.
Portanto o macboxgray é uma derivação da classe rounded, uma implementação específica da classe “rounded”.

Conseguem entender o que estou querendo dizer?

Importando as duas classes, eu só precisaria mexer nas definições específicas para aquela tela que estou montando, dando margin, padding, float etc. Lembrando que nesta solução, eu teria de alterar o width na classe .macboxgray e alterar a altura no .macboxgray .r-content, já que o .r-content que detêm o conteúdo, poderia deixar um tamanho fixo por exemplo com scroll ou deixa-lo no padrão, em auto, crescendo conforme o conteúdo cresce.

Prestem atenção, embora eu tenha utilizado classes para os elementos html, neste post essas classes são implementadas conforme seu uso na linguagem Css reaproveitando comportamentos iguais, não são dessas classes que estou falando, estou falando da classe “Rounded”, uma classe que existe apenas na nossa cabeça, um tipo de objeto que é nossa solução para caixas arredondadas e que poderá ser estendido futuramente para outros tipos de caixa, também de bordas arredondadas.

Isso é um exemplo de como enxergar as coisas como objetos no Css. Um dia eu pensei nisso e acho que esta forma de pensar trás, além de reuso de código, visão simples e organizada do código Css, tornando muito mais estensível a linguagem do que já é, são inúmeras as possibilidades do que pode ser feito pensando dessa forma.

Pensa num objeto layout, que pode ser do tipo líquido ou fixo por exemplo, olha que coisa louca….pode viajar, foda né?

O Diego Eis mostrou no tableless.com.br uma implementação de layout líquido e com apenas uma alteração ele passava a ficar fixo. Olha aí uma idéia para uma outra classe…

Outra coisa boa é que, eu testei exaustivamente esta implementação de borda arredondada e funcionou muito bem, então, na hora de fazer um outro tipo de objeto que o estenda, perderei menos tempo com os bugs já resolvidos com esta implementação bem sucedida.

Quando criei o macboxgray, não precisei de novo me preocupar com os problemas das bordas arredondadas, elas já estavam solucionadas, precisei apenas pensar nos seus problemas pontuais.

Css não tem métodos, portanto, para sabermos da sua implementação na prática precisamos de uma documentação.
Este código acima html é colocado como exemplo dentro do comentário do rounded.css, para que um dia ao reutilizar o código, basta colar e será mais rápido de lembrar do seu funcionamento.

Então é muito importante uma mínima documentação, lá no código do macboxgray, deixei nos comentários que ele precisa da classe .rounded, na palavra-chave “required”. Lógico, não é necessário de novo colocar o exemplo do html dentro deste código, já que ele herda de rounded e já está lá seu exemplo.

Essa técnica particiona ao máximo o seu Css, aumentando consideravelmente o número de arquivos se você for uma pessoa criativa, então é interessante ser bem organizado na sua estrutura de pastas, até pensando em montar um próprio framework.

Terá casos onde será melhor você utilizar um único arquivo Css ao invés de ficar importando vários objetos de pequenos arquivos, consumindo a banda, então use o bom-senso para estes casos, copie os códigos e cole em um arquivo único, comprima-o se necessário, algumas linguagens server-side já fazem isso dependendo do framework que esteja usando, Rails faz isso. De qualquer forma no Css, desde que esteja bem encapsulado, juntar é muito mais fácil do que separar.

É claro que esta solução tem também suas desvantagens. Uma é que o código fica um pouco maior do que o necessário no html.
Mas pessoalmente acho um preço muito baixo a se pagar, se tiver a certeza de que funciona nos navegadores que deseja.

Eu usei aquela mesma solução de bordas arredondadas de um post meu, “Bordas Arredondadas”, lembra? Porém dei uma enxugada maior no código css e alterei algumas coisinhas.

That´s all folks! Espero que tenham entendido minha idéia e se alguém aí tiver mais idéias, por favor poste que eu quero saber!

Quem quiser ver como ficou a implementação das bordas clique aqui, visualize o código fonte para entender o que fiz.

Um grande abraço.

Anúncios