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

12 comentários sobre “Css Orientado a Objetos

    • Olá Thiago tudo bom ?

      Na verdade essas idéias vieram por parte da minha cabeça e parte dos estudos de orientação à objetos que estava lendo na época. O post é um pouco antigo, acho que hoje eu faria as bordas arredondadas de outra forma, mas a idéia de usar os conceitos de orientação à objetos em Css foi minha mesmo. Lembro de ter pesquisado na época sobre o assunto e não achei nada neste naipe… Então resolvi usar os conceitos que OOP para tentar resolver um problema que eu estava enfrentando na época pra iniciar um estudo assim.

      Ah, se vc tiver um link sobre o assunto, que eu não tenha conhecimento, gostaria muito que compartilhasse. =)

      Um grande abraço.

      • E aí Marcelo, beleza?

        É claro que isso não foi idéia minha, muita gente pensa em orientação à objetos em Css, quando se pensa em otimizar o código, herdar e usar corretamente as classes.
        Na tentativa de melhorar o código Css, com certeza você cairá nos tópicos de OO ou Modularização.

        []’s

  1. Gostei do artigo, tive contato com esse conceito no começo do ano passado.

    Nós utilizamos herança para desenvolver algumas páginas, mas da forma que fizemos foi errado.

    Porém usamos esse conceito, hoje minha ídeia seria essa:

    O site continha várias seções muito parecidas por sinal.(afinal todo site segue +- um padrão senão vira palhaçada).
    Lembro que na época desenvolviamos e paralelo, se página era muito semelhante usavamos herança. (Mas tinha um problema: não havia uma página genérica e nem divisão o que foi o maior erro de todos).

    Então toda vez que alguém alterava a seção 1, automáticamente mudava as filhas.

    Hoje eu faria o seguinte: Criaria uma classe mãe genérica(com as características comuns de todas as páginas).

    Essa não poderia ser mexida, a não ser que quisesse mudar todo o layout do site.

    Extenderia ela para todas as outras seções.

    .layoutPadrão . secao1{
    Aqui viria o código especifico
    }
    .layoutPadrão . secao2{
    Aqui viria o código especifico
    }
    .layoutPadrão . secão3{
    Aqui viria o código especifico
    }
    .layoutPadrão . secao4{
    Aqui viria o código especifico
    }

    assim por diante…

    Para aquele problema eu acho que é mais lógico dividir por seção, uma vez que o cliente mudava de idéia constantimente.
    (Não sei se é o melhor jeito,mas assim me parece mais flexível).

    Como o colega disse a parte mais importante não é herança em sí, mas sim a abstração do problema.
    Apenas usar herança vai gerar mais dor de cabeça.

    Gostei muito do artigo.

    • E aí João, tudo bom?

      Realmente, o Css é muito particular, não acho uma boa generalizar uma solução para todos os problemas, concordo com você, cada caso é necessário ser estudado separadamente porque depende do projeto, da particularidade do projeto.

      Obrigado pelo comentário e por compartilhar seu conhecimento também.

      Abraço

    • Boa Lucas, infelizmente o iE6, iE7 e o IE8 não possuem suporte ao Css 3.
      O maior problema é resolver em browsers em que este código não funciona.

      []’s

  2. Gostei muito do post. A Orientação a Objetos torna a programação muito mais organizada e de fácil entendimento. Adaptar esse paradigma para o CSS é uma ótima ideia.
    Estou começando a criar meus CSS orientado a objetos, mas existem algumas coisas um pouco obscuras.
    Quero criar uma única caixa maior com 3 caixas menores (de tamanhos iguais) dentro desta maior. Depois, dentro dessas caixas menores existiram outras divisões. Mas estou me deparando com um problema estranho. Eu defino as 3 caixas com os mesmos tamanhos, porém a terceira fica menor. Não consegui entender o porque.
    Abaixo segue o código:

    .Caixa,
    .Caixa .Caixa1,
    .Caixa .Caixa2,
    .Caixa .Caixa3

    .Caixa .Caixa1 .ECaixa,
    .Caixa .Caixa1 .DCaixa

    .Caixa .Caixa2 .ECaixa,
    .Caixa .Caixa2 .MCaixa,
    .Caixa .Caixa2 .DCaixa

    .Caixa{
    width: 590px;
    height: 300px;
    background-color:#000;
    display:block;
    padding-left:10px;
    padding-top:10px;
    }

    .Caixa .Caixa1{
    width:570px;
    height: 90px;
    background-color:#090;
    }

    .Caixa .Caixa2{
    width:570px;
    height: 90px;
    background-color:#339;
    }

    .Caixa .Caixa3{
    width:570px;
    height: 90px;
    background-color:#C60;
    }

    • Oi Gustavo tudo bem? Obrigado pelo comentário =)

      Então, eu colei seu código aqui e não vi essa diferença de tamanho que comentou. Mas eu tenho algumas considerações no seu código. Usar Orientação à Objetos é principalmente se preocupar com o reuso do código, tem partes que você copia e que seria interessante usar herança. Outra coisa, raramente nós precisamos dar uma altura para um elemento, geralmente queremos que ele cresça para baixo. E se temos essas caixas filhas de uma caixa maior, não é interessante dar uma largura para essas caixas e sim deixá-las em largura automática, uma vez que se precisar aumentar o tamanho da caixa pai, as filhas irão acompanhar esse aumento, sem a necessidade de ter de mudar todas as larguras novamente.

      Reescrevi seu código da seguinte forma:

      .caixa{
      padding:20px;
      width: 590px;
      background-color:#000;
      }

      .caixa-interna{ height:90px }

      .caixa1{
      background-color:#090;
      }
      .caixa2{
      background-color:#339;
      }
      .caixa3{
      background-color:#C60;
      }

  3. Obrigado pela resposta.
    Agora que percebi que o meu código foi incompleto, mas consegui perceber que estou copiando códigos de forma desnecessária e fiz alguns ajustes. Eu tenho alguns problemas em posicionar elementos lado a lado. Por exemplo quando coloco duas divs lado a lado usando o float:left; os comandos para centralizar o texto verticalmente display: table-cell e vertical-align: middle; param de funcionar. Ou seja, o comando float:left; anula os comandos display: table-cell; e vertical-align: middle; Se alguém já tiver se deparado com esse problema e conseguiu alguma solução elegante, compartilhe com agente.
    Abraço!

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s