Tableless - Desenvolvimento inteligente com Padrões Web

30/05/2011
Acessibilidade

CSS3 – Módulo Template Layout

Entenda como você não fará mais estruturas com a propriedade float.

Por


Talvez você me chame de louco, mas para mim a parte mais fácil de desenvolver um site com CSS é o planejamento e diagramação do layout. Coincidentemente é a parte que mais os desenvolvedores tem problemas crossbrowser ou por falta de recursos mais avançados. Mas se você parar para pensar, apenas uma propriedade cuida dessa parte, que é a propriedade float. De longe, para mim, o float é a propriedade mais importante que há no CSS. Se o IE não soubesse o que é float, até hoje nós não estaríamos fazendo sites com CSS. O float cuida de toda a diagramação do site, desde os elementos que definirão as áreas mestres do site até os pequenos detalhes de imagens e ícones.

A propriedade float é muito simples de se entender. O problema não é o funcionamento, mas os efeitos que a propriedade float causa nos elementos próximos. Se você pede para duas colunas ficarem flutuando à esquerda e outra coluna à direita, o rodapé sobe. Ou se você coloca um elemento envolvendo outros elementos com float, esse elemento perde a altura. Estes são problemas corriqueiros que já tem soluções inteligentes e que não apresentam chateações mais graves.

Infelizmente o float não é o ideal para a diagramação e organização dos elementos do layout. Ele resolve muitos problemas, mas deixa a desejar em diversos sentidos. O float está completamente ligado a ordem dos elementos no HTML. Existem técnicas que você consegue fazer quase que qualquer oganização visual sem encostar no código HTML. Mas há outras necessidades que invariavelmente você precisará modificar a ordem dos elementos no meio do HTML para que a diagramação do site saia conforme o esperado. Essa organização do HTML pode alterar desde programação server-side e até resultados de SEO e acessibilidade. Por isso é interessante que o HTML fique organizado de forma que ele supre as necessidades dessas bases. Sua organização visual deve ser independente desta organização.

Tendo em vista estes e outros problemas o W3C criou um novo módulo. Na verdade ele não é o único, e nem pode ser para que tenhamos diversas formas de trabalhar. O módulo em questão é chamado de Template Layout. Esse módulo consiste em uma forma de criarmos e organizarmos os elementos e informações do layout de forma menos espartana e mais flexível.

Podemos dividir a construção do layout em duas grandes partes: 1) Definição dos elementos mestres e grid a ser seguido. 2) Formatação de font, cores, background, bordas etc.

As propriedades nesta especificação trabalham associando uma política de layout de um elemento. Essa política é chamada de template-based positioning (não tem nada a ver com a propriedade position, pelo contrário é uma alternativa) que dá ao elemento uma grid invisível para alinhar seus elementos descendentes.
Porque o layout deve se adaptar em diferentes janelas e tamanhos de papéis, as colunas e linhas do grid deve ser fixas ou flexiveis dependendo do tamanho.

O W3C mostra alguns casos comuns:

  • Páginas complexas com múltiplas barras de navegação em áreas com posições fixas como publicidade, submenus e etc.
  • Formulários complexos, onde o alinhamento de labels e campos pode
    m ser facilmente definidos com as propriedades deste módulo com a ajuda das propriedades de margin, padding e tables.
  • GUIs, onde botões, toolbars, labels,
    ícones etc, tem alinhamentos complexos e precisam estar sempre alinhados caso o tamanho ou a resolução da tela mudam.
  • Medias que são paginadas, como medias de impressão onde cada página são divididos em áreas fixas para conteúdos de gêneros diferentes.

Template-based positioning são uma alternativa para a propriedade position com o valor absolute. Antigamente lembro-me que quase todos os desenvolvedores tentavam organizar e diagramar layouts utilizando position. Não que seja errado, mas definitivamente não é a melhor forma. Costumo dizer em meus cursos e palestras que position é para detalhes. Nada muito grande, mas para pequenos detalhes. Usamos position para posicionarmos elementos que não tem relação direta com sua posição no código HTML. Ou seja, não importa onde o elemento esteja, o position:absolute; irá posicionar o elemento nas coordenadas que você quiser.

Sintaxe e funcionamento

O módulo Template Layout basicamente define slots de layout para que você encaixe e posicione seus elementos. O mapeamento dos slots é feito com duas propriedades que já conhecemos que este módulo adiciona mais alguns valores e funcionalidades, são as propriedades position e display.

A propriedade display define como será o Grid, ou seja, quantos espaços úteis terá o layout.
A propriedade position irá posicionar seus elementos nestes slots.

Veja o código HTML abaixo:

1
2
3
4
5
6
7
<div class="geral">
  <nav class="menu">...</nav>
  <aside class="menulateral">...</aside>
  <aside class="publicidade">...</aside>
  <article class="post">...</article>
  <footer>...</footer>
</div>

Agora iremos definir a posição destes elementos. O código CSS seria assim:

1
2
3
4
5
6
7
8
9
10
11
.geral {
   display: "aaa"
            "bcd"
            "eee";
}

nav.menu {position:a;}
aside.menulateral {position:b;}
aside.publicidade {position:d;}
article.post {position:c;}
footer {position:e;}

O funcionamento da propriedade display

A propriedade display define a organização dos slots. Um slot é o local onde os elementos serão colocados.
Aqui o elemento display trabalha como um table, onde seu conteúdo será colocando em colunas e linhas. A única diferença é que o número de linhas e colunas não dependem do conteúdo. A outra principal diferença é que a ordem dos descendentes no código não importa. Ou seja, não importa a estrutura dos elementos no HTML, você pode colocá-los em qualquer lugar do layout.

Cada letra diferente é um slot de conteúdo diferente. O @ define um sinal para um slot padrão. E o “.” (ponto) define um espaço em branco.

Quando repetimos as letras como no exemplo anterior, tanto na horizontal quanto na vertical, é formado um slot único que se expande para o tamanho da quantidade de slots. Lembra do colspan ou rowspan utilizados na tabela? Pois é, funciona igualzinho.

Não é possível fazer um slot que não seja retangular ou vários slots com a mesma letra. Um template sem letra nenhuma também não é possível. Um template com mais de um @ também é proibido. Se houverem esses erros a declaração é ignorada pelo browser.

Pra definir a altura da linha (row-height) podemos utilizar o valor padrão “auto”, que define altura que a altura da linha é feito de acordo com a quantidade de conteúdo no slot. Você pode definir um valor fixo para a altura. Não é possível definir um valor negativo. Quando definimos um * (asterísco) para a altura, isso quer dizer que todas as alturas de linha serão iguais.

A largura da coluna (col-width) é definida com valores fixos, como o row-height. Podemos definir também o valor de * que funciona exatamente igual ao altura de linha, mas aplicados a largura da coluna. Há dois valores chamados max-content e min-content que fazem com que a largura seja determinada de acordo com o conteúdo. Outro valor é o minmax(p,q) que funciona assim: a largura das colunas são fixadas para ser maiores ou iguais a p e menores ou iguais a q. Pode haver um espaço branco (white space) em volta de p e q. Se q > p, então q é ignorado e o minmax(p,q) é tratado como minmax(p,p). O valor fit-content é o equivalente a minmax(min-content, max-content).

Definindo a largura e altura dos slots

Para definir a altura dos slots, utilizamos uma sintaxe diretamente na propriedade display. Veja abaixo um exemplo de como podemos fazer isso:

1
2
3
4
5
6
.geral {
  display: "a a a" /150px
           "b c d"
           "e e e" / 150px
           100px 400px 100px;
}

Formatando de uma maneira que você enteda, fica assim:

1
2
3
4
5
6
.geral {
  display: "a          a           a" /150px
           "b          c           d"
           "e          e           e" /150px
           100px      400px      100px;
}

Ou seja, a primeira coluna do grid terá 100px de largura, a segunda 400px e a terceira 100px.
As medidas que coloquei ao lado, iniciando com uma / (barra) definem a altura das linhas. Logo a primeira linha terá 150px e a terceira linha também. A linha do meio, como não tem altura definida terá a altura de acordo com a quantidade de conteúdo.

O espaço entre as colunas são definidos com “.” (pontos). Veja o exemplo abaixo:

1
2
3
4
5
6
7
8
.geral {
  display: "a          a           a" /150px
           ".          .           ." /50px
           "b          c           d"
           ".          .           ." /50px
           "e          e           e" /150px
           100px      400px      100px;
}

No exemplo acima fiz duas colunas no código compostos por pontos em vez de fazer com letras. Isso quer dizer que entre as colunas do grid haverá um espaço em branco de 50px de altura. Veja a imagem abaixo para entender melhor o código:

O funcionamento da propriedade position

O valor da propriedade position especifica qual linha e coluna o elemento será colocado no template. Você escreve apenas uma letra por elemento. Vários elementos podem ser colocados em um mesmo slot. Logo estes elementos terão o mesmo valor de position.

Abaixo veja uma imagem que pegamos diretamente do exemplo do W3C. O layout é muito simples:

Este layout é representado pelo código abaixo. Primeiro o HTML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<ul id="nav">
     <li>navigation</li>
</ul>
<div id="content">
    <div class="module news">
         <h3>Weather</h3>
         <p>There will be weather</p>
    </div>
    <div class="module sports">
         <h3>Football</h3>
         <p>People like football.</p>
    </div>
    <div class="module sports">
         <h3>Chess</h3>
         <p>There was a brawl at the chess tournament</p>
    </div>
    <div class="module personal">
         <h3>Your Horoscope</h3>
         <p>You're going to die (eventually).</p>
    </div>
    <p id="foot">Copyright some folks</p>
</div>

Agora veja o CSS com toda a mágica:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
body {
     display: "a     b"
              10em   *;
}
#nav {
     position: a;
}
#content {
     position: b;
     display: "c   .   d   .   e "
              ".   .   .   .   . "  /1em
              ".   .   f   .   . "
               *  1em  *  1em  *;
}
.module.news {position: c;}
.module.sports {position: d;}
.module.personal {position: e;}
#foot {position: f;}

Lembre-se que não importa a posição dos elementos no código. E essa é a mágica. Podemos organizar o código HTML de acordo com nossas necessidades e levando em consideração SEO, Acessibilidade e processo de manutenção. O HTML fica totalmente intacto separado de qualquer formatação. Muito, mas muito interessante.

Pseudo-elemento ::slot()

Você pode formatar um slot especifico simplesmente declarando-o no CSS. Suponha que você queira que um determinado slot tenha um fundo diferente, alinhamento e etc… Essa formatação será aplicada diretamente no slot e não no elemento que você colocou lá. Fica mais simples de se formatar porque você não atrela um estilo ao elemento e sim ao slot. Se você precisar posicionar aquele elemento em outro lugar, você consegue facilmente.

1
2
3
4
body { display: "aaa"
                "bcd" }
body::slot(b) { background: #FF0 }
body::slot(c), body::slot(d) { vertical-align: bottom }

As propriedades aplicadas no pseudo elemento slot() seguem abaixo:

  • Todos as propriedades background.
  • vertical-align
  • overflow
  • box-shadow, block-flow e direction ainda estão sendo estudados pelo W3C se elas entrarão ou não.

Mas e o float?

É senhores… Eu acho que o float tem seus dias contados para a criação de estruturas de layouts. Quando utilizamos o float para estruturar o layout, nós dependemos profundamente da organização e posição dos elementos no código HTML. Não estou dizendo que o float ficará obsoleto, você ainda vai utilizá-lo e muito. Você vai pará-lo de utilizar para criar a base estrutural do site. Ou seja, a estrutura básica de divisão de conteúdo será feita pelo Template Layout, mas muitos dos detalhes internos e organização dos elementos contidos nos elementos mestres serão feitos com float.

Com o Template Layout a estrutura do layout não depende da posição dos elementos do HTML no código, você poderá otimizar o código ao máximo para os leitores de tela e sistemas de busca, já que estes meios de acesso prezam pela estrutura do seu conteúdo.

Já funciona?

Sim, já funciona, mas não nativamente nos browser. Esta especificação ainda é um rascunho do W3C e por isso os browsers ainda não a suportam. Mesmo assim um desenvolvedor criou um script em Javascript que entende o CSS desta especificação e simula os resultados. Você pode baixar o script aqui.

Veja um exemplo funcionando aqui.

Por Diego Eis

Diego Eis criou o Tableless para disseminar os padrões web no Brasil. Como consultor já treinou equipes de empresas como Nokia, Globo.com, Yahoo! e iG. É palestrante e empreendedor.

http://twitter.com/diegoeis/

Veja os outros posts de

  • leandro kanis

    voltamos às tabelas?

  • Rodrigo

    Muito boa essa funcionalidade!
    Mas como sempre, no ie não funcionou… Se funcionasse no ie8 pelo menos, já era alguma coisa que poderia pensar para desenvolver.

    Parabéns mais uma vez!

  • http://twitter.com/jardel_xavier Jardel Xavier

    Com essa evolução será possível desenvolver layouts complexos de maneira simples, espero que os Browser passem a suportar estes recursos logo. Parabéns e obrigado pela ótima explicação dos elementos, Artigo excelênte.

  • http://eduardodesign.com Eduardo

    Muito legal! Show de post!

    @Jardel > Vamos torcer mesmo que os browsers suportem isso. Chrome e Firefox são relativamente rápidos pra atualiza-los, mas IE demora um pouco – pra tudo. Espero que essa política de atualização mude rápido.

  • http://hajaluz.webluz.net Luiz Aquino

    Diego, muito bacana a postagem. Não sou radical para nenhum dos dois lados. O grid sair vai ser útil dentro de um determinado conceito, enquanto o float pode ser mais útil em outro.

    Assim como em um site tabular vamos utilizar e está tudo ok.

    Pelo que você expôs o grid será um meio termo, muito bem vindo.

    E se alguém ainda não sabe, não tem nada de mais limpar o float com clear:both, clear:left ou clear:right, tudo fica ok sem problemas.

  • Gedean

    Olá Diego! Me matei na apostila da W3C Brasil e não consegui fazer funcionar, não ví menção ao plugin do jQuery que estou vendo aqui, apesar de já ter visto no site/blog do Maujor. Agora vai!

    Abraço.

  • http://www.vitorgga.com VitorGGA

    Só tem uma hora ali que os . tem altura de 50px que eu não consegui identificar onde estão setados esses 50px, podem ajudar eu? :)

  • http://twitter.com/rafelcavalcante rafael

    Maravilha de artigo! Isso via facilitar muito… pena que vamos ter que esperar algum “hack” pra que isso funcione no IE.

  • http://www.wilsoncsousa.com.br Wilson Carlos

    Muito bom o artigo, parabéns Diego.
    Fico me perguntando até quando teremos que ficar com um pé atrás em usar essas funcionalidades por conta do iE*.
    Como explicar ao cliente que seu site não pode ser exibido corretamente em tal browser porque o mesmo não suporta determinado recurso?
    Espero que o iE possa um dia ser atualizado no mesmo ritmo em que os desenvolvedores lançam novos projetos.

    Parabéns novamente!

  • João Henrique

    Parabéns Diego, artigo muito interessante, mas quanto mais eu leio mais eu enxergo table, parece exatamente a mesma lógica de estrutura de uma tabela, seguindo matrizes. Mesmo assim não deixa de ser interessante.

  • http://twitter.com/oieduardorabelo Eduardo Rabelo

    Eu achei esplendido esse módulo do css!

    Sinceramente, fica muuuuuuuuuuito mais simples organizar a estrutura do site,

    Até mesmo os detalhes, é possível fazer display dentro de display e por aí vai, só soltar a imaginação!

    Demais o post,

    Ansioso para ler o livro de CSS que você revisou! :D

  • http://www.nandokstro.net Nanderson Castro

    Sou cada vez mais apaixonado por padroes web em especial html e css! tao muito bons mesmo! parabens pelo post e belissimo site! bem agradavel esta aqui!

  • http://www.theossi.com Felipe

    Ótimo post, valew!

    Sem querer achei esse especificação no site da W3C, segue o link!!!
    http://www.w3.org/TR/2009/WD-css3-layout-20090402/

  • js

    O esquema é muito interessante, mas não pode ser utilizado pois não funciona em IE8.

  • Nio

    Huahuahua. Uma prova de q, em alguns casos, mais vale usar a velha tabela.

  • http://twitter.com/diegoeis/ Diego Eis

    Nio, eu acho que você não entendeu. O Template Layout não tem NADA a ver com tabelas. Embora uma ou outra característica de montagem seja parecido com tabelas, todo o conceito e até mesmo a forma de montar é totalmente diferente. A ideia do Template Layout é retirar a necessidade de termos uma ordem específica no HTML para podermos formatar o layout pelo CSS.

  • # Rotoy Santos

    Parabéns pelo artigo, como sempre, nota 10!

  • Tiago

    Olá!

    Dúvida de um cara desatualizado: posso misturar as larguras em pixels e porcentagens? Por exemplo, no topo AAA posso usar 100% de largura ao invés de 150 pixels, e no resto apenas pixels?

    Um abraço!

  • João Daniel

    Excelente artigo, Diego. Ainda não tinha lido sobre essa abordagem e, agora que li, fiquei bastante animado para poder usar isso de forma nativa pelo menos no Chrome e Firefox. Será que isso chega rápido pra gente?

    Recentemente li um artigo falando sobre uma abordagem diferente para essa parte de diagramação de layout usando a técnica de Flexible Box Model, basicamente usando display: box; e manipulando cada “slot” desse caso com :nth-child(n). Me pareceu bastante interessante, mas confesso que fico na dúvida agora se essa seria a abordagem mais correta. Já chegou a ver algo nesse sentido? Se sim, qual sua opinião?

    Abraço!

  • Lucas Câmara

    Realmente, isto facilitará e muito nosso trabalho. Caiu do Céu!

  • http://www.felipekm.com Felipe Kautzmann de Mello

    Excelente artigo, explicativo e bem estruturado.

  • http://leobalter.net Leo Balter

    Curti. A implementação é diferente mas vale a pena experimentar.

  • http://www.gabrielmagalhaes.com.br Gabriel Magalhães dos Santos

    Muito legal o post, fiquei curioso

    mais quando passo o firebug, o plug in enche de style os elementos e acaba usando position, float, width, etc…

  • Diane

    Muito interessante seus posts, poderia abordar mais assuntos relacionados a CSS.

    Parabéns pelo site.

  • http://www.chemale.com.br Vinícius Chemale

    Muito bom! Só que não funcionou em nenhuma versão do IE. Pra variar.
    E segundo o que consultei, o html 5 é bom para animações e iOS. Vai entender…

  • Rafael Dias

    Olá amigo!

    Realmente não funciona em IE, além disso ele também apenas funciona com o CSS embutido no código HTML, não rola com CSS externo.

    É uma pena, pois estava realmente animado em começar a usar esta abordagem, mas sem dúvida já foi ótimo para sentir como será utilizar a abordagem, agora só podemos torcer para que os navegadores passem logo a suprota-la!

  • http://rickbenetti.com Rick Benetti

    Olha o assunto é realmente complexo devido as suas inúmeras possibilidades, porém como ainda está em estudo e não tá bem montado isso, e depender de um script pra gerar as colunas ou blocos a meu ver acaba mais atrapalhando do que ajudando.
    Porém é muito bom ver que estamos evoluindo, espero em breve poder usar o CSS3 Template, mas até lá, bora no float: left rs

  • http://twitter.com/davilandre20 Davil André

    Essa nova forma do layout é interessante, mas vai ser difícil assimilar tantas informações para criar-se uma página. Mas vamos em frente, o futuro não espera gente!

  • Fabio Novais

    Para mim funcionou normalmente no IE7 e IE8, só que somente com o CSS incorporado na página. Não funcionou quando coloquei o mesmo CSS em uma folha externa. Vi um exemplo indicando para passar o nome do arquivo CSS como parâmetro para a função que habilita o plugin, mas também não deu certo. 
    Alguém sabe como solucionar?

  • http://csharpbrasil.com.br/ Raphael Cardoso

     Olá Diego, tudo bem?
    Excelente abordagem.
    Analisando o exemplo, o CSS referente ao header e ao footer estão trocadas o que fez com que o header fique alinhado no rodape e o footer no cabecalho. Mais analisando vi que é bem interessante é de facil correção.Parabens!