Visão geral do Flexible Box Model

HTML5 Rocks

Introdução

Aposto que você já gastou um bom tempo organizando elementos de maneira horizontal ou vertical em uma página. Até agora, no entanto, o CSS não oferecia um mecanismo adequado para a tarefa. Apresentamos o Modelo de box flexível CSS3, ou, resumidamente, Flexbox.

Este rascunho descreve o Flexbox como:

[...] um modelo de box CSS otimizado para design de interfaces. Além disso, ele oferece um sistema adicional de criação de layout além dos já oferecidos no CSS. [CSS21] Neste novo modelo de boxes, os filhos de um box são organizados horizontal ou verticalmente e o espaço não utilizado pode ser atribuído a um filho específico ou distribuído entre os filhos por atribuição de "flex" aos filhos que devem ser expandidos. O aninhamento desses boxes (horizontal dentro de vertical ou vice-versa) pode ser utilizado para construir layouts em duas dimensões. Este modelo é baseado no modelo de box na linguagem de interface XUL utilizada para a interface do usuário de muitos aplicativos baseados no Mozilla (como o Firefox).

Ótimo. Para desenvolvedores, ou melhor, Arquitetos de Layout™ como você, isso significa:

  1. Floats? Para onde vamos, não precisamos de floats.
  2. Layouts que costumavam ser desafiadores agora são mais práticos.
  3. Podemos criar layouts flexíveis e o navegador fará os cálculos por nós.

O Flexbox fornece um novo valor para a propriedade display (o valor box) e oito novas propriedades:

  • box-orient
  • box-pack
  • box-align
  • box-flex
  • box-flex-group
  • box-ordinal-group
  • box-direction
  • box-lines
Oito novas propriedades? É muita coisa, não? Tudo bem, vamos por partes.

Propriedades comuns de estilo em flexbox

Estilos utilizados no box

display: box
Este novo valor para estilo de display configura este elemento e seus filhos imediatos no modelo de box flexível. O modelo flexbox só funciona com filhos imediatos.
box-orient
Valores: horizontal | vertical | inherit
Como os filhos de um box devem ser alinhados? Existem dois valores adicionais inline-axis (o padrão real) e block-axis, que mapeiam como horizontal e vertical, respectivamente.
box-pack
Valores: start | end | center | justify
Determina o alinhamento do box ao longo do eixo de box-orient. Então, se box-orient for horizontal, determinará como os filhos do box serão alinhados horizontalmente e vice-versa.
box-align
Valores: start | end | center | baseline | stretch
Basicamente, a propriedade irmã de box-pack. Determina como os filhos do box serão alinhados no box. Se a orientação for horizontal, determinará o alinhamento como vertical e vice-versa.

Estilos utilizados nos filhos do box

box-flex
Valores: 0 | Qualquer número inteiro
A razão de flexibilidade para este filho. Se um filho tiver 1 e outro filho 2, qualquer espaço adicional no box que originou esses dois será consumido em dobro pelo segundo filho. O padrão é 0, que é inflexível.

As propriedades box-flex-group, box-ordinal-group, box-direction e box-lines foram deixadas de fora das descrições acima porque não costumam ser necessárias na maior parte dos trabalhos com flexbox. Acesse os links no resumo para ver essas propriedades em uso.

Uma observação sobre a sintaxe: as implementações atuais de flexbox em WebKit e Gecko requerem o uso de prefixos de fornecedor. Esses casos não foram incluídos neste tutorial para manter a clareza. Para obter mais detalhes, leia a seção suporte a navegadores.

O que é flexibilidade?

A propriedade de estilo box-flex define se um filho de flexbox deve ser flexível ou não e ajuda a definir a razão de flexibilidade em relação a outros filhos. Vamos demonstrar o que isso quer dizer. Primeiro, começamos com três boxes.
<div id="flexbox">
  <p>child 1</p>
  <p>child 2</p>
  <p>child 3</p>
</div>

Agora, vamos organizá-los horizontalmente lado a lado. Os valores de altura desses boxes devem sempre ser correspondentes, independentemente do conteúdo. Qual a melhor forma de abordar isso? A maioria das pessoas imediatamente deixaria esses parágrafos em float, talvez adicionando overflow:hidden; ao box pai para limpar os floats. Nada muito especial. Isso também pode ser feito facilmente com flexbox:

#flexbox { 
  display: box;
  box-orient: horizontal;
}

No código acima, simplesmente dizemos ao box pai para comportar-se conforme este modelo de flexbox e dispor todos os filhos ao longo do eixo horizontal. Sem floats. Isso aí.

A largura dos filhos permanece como especificada (ou sua largura inerente, caso não seja especificada). Isso significa que, se a largura total de todos os filhos for menor que a largura total do pai, teremos algo assim:

três elementos filhos que mantenham suas larguras inerentes dentro do elemento pai

Por padrão, filhos de um flexbox mantêm-se inflexíveis. Isso pode soar um pouco estranho, mas permite que os filhos optem por uma experiência flexível. E se você quiser que os filhos um e dois tenham larguras específicas e o filho três se ajuste conforme o espaço disponível no pai? Flexbox vem ao resgate:

#flexbox { 
  display: box;
  box-orient: horizontal;
}
#flexbox > p:nth-child(3) {
  box-flex: 1;
}

Aqui, dizemos ao último filho que se torne flexível e ocupe o espaço disponível. Já que alocamos espaço apenas para um elemento, ele ocupará todo o espaço disponível:

O terceiro elemento filho, configurado como flexbox, ocupa todo o espaço disponível.

O elemento só passa a ser flexível ao longo do eixo de orientação do box. Nesse caso, o elemento torna-se flexível somente na horizontal.

O valor do box-flex é relativo. Para fazer com que o segundo e o terceiro filhos sejam flexíveis:

#flexbox { 
  display: box;
  box-orient: horizontal;
}
#flexbox > p:nth-child(2),
#flexbox > p:nth-child(3) {
  box-flex: 1;
}

Eles tomariam a mesma quantidade de espaço disponível, dividindo-o igualmente entre si.

dois entre os três elementos filho compartilham o espaço disponível no elemento pai.
Agora podemos também testar diferentes configurações de box-flex dos filhos 1, 2 e 3 para que sejam respectivamente1, 2, 3 e absorvam o espaço extra do box pai nessa proporção. Mas, em vez disso, vamos testar na prática.

Um exemplo básico

Veja o código e o resultado abaixo:

Passe o cursor do mouse sobre um dos boxes abaixo para ver o box flexível em ação: Ao passar o cursor, o alvo se expande e os boxes restantes diminuem em tamanho, mas a largura total é sempre exatamente igual ao tamanho do box pai.

Apenas dois estilos estão em jogo aqui: o display: box põe os elementos no modo flexbox e o box-flex: 1 nos filhos os faz operar no modo flexível, tomando todo o espaço extra disponível. A orientação padrão é horizontal, então o comando box-orient: horizontal não é realmente necessário. No entanto, é bom incluí-lo para manter a clareza e facilidade de manutenção. O valor padrão de box-align é a extensão e é por isso que estas divs ocupam integralmente a altura do box pai. Nada mal, hein? Você pode ver esta técnica usada em navegação nesta demonstração do flexiblenav por Raphael Goetter.

Vamos elaborar mais um pouco.

Centro das atenções: posicionamento no centro

Centralizar algo horizontal ou verticalmente sempre foi um desafio no CSS. A melhor solução exclusiva para CSS que temos é position:absolute; left: 50%; top: 50%; aliada a margens negativas superiores e da esquerda que somam metade da largura/altura. Isso funciona somente com elementos de tamanhos especificados. Ai!

James John Malcom escreveu para contar que existe uma forma, baseada em display:table-cell; que existe há, no mínimo, seis anos (Dušan Janovský escreveu sobre isso em 2004), para fazer o alinhamento vertical. James documentou aqui a solução horizontal e vertical completa. Funciona até mesmo com elementos sem tamanho expresso.

Com o flexbox, isso fica um pouco mais fácil:

Não configuramos box-flex no filho porque não queremos que ele utilize espaço extra. Só queremos que ele fique no centro, independentemente de seu tamanho. A grande vantagem é esta: não precisamos de dimensões especificadas para centralizá-lo. Poderíamos fazer isso com algo que seja tipicamente bloco ou in-line. Simplesmente funciona.

Suporte a navegadores

Você pode usar o modelo de box flexível em seu trabalho atualmente? Ainda não, se você deseja compatibilidade com todos os navegadores. Até agora, não vimos o flexbox no IE9 ou no Opera 10.60, mas ele já está presente em um preview da Plataforma IE9, então é provável que a Microsoft o adicione em algum momento.

O Caniuse.com oferece o status atual de compatibilidade com navegadores, que hoje inclui basicamente Firefox 3+, Safari 3+ e Google Chrome. Para desenvolvimento móvel com webkit, o flexbox é uma ótima alternativa para seus esquemas de layout padrão.

Como isso ainda está em fase experimental, prefixos de fornecedor são as melhores opções:

/* i wish it was as easy as this: */

display: box;
box-orient: horizontal; 
box-pack: center;
box-align: center;
  
/* but in reality you'll need to do this: */

display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack: center;
-webkit-box-align: center;

display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-pack: center;
-moz-box-align: center;

display: box;
box-orient: horizontal;
box-pack: center;
box-align: center;
  

Se isso parece exigir muita digitação, veja todas estas opções resumidas por Alex Russell em algumas classes auxiliares úteis (link em inglês).

Resumo

Mesmo sem considerar as outras quatro propriedades, já dispomos de muitas opções. Para conhecer mais sobre o flexbox, veja as demonstrações do flexbox da Isotoma e as postagens do Mozilla Hacks sobre flexbox (links em inglês). As especificações do Flexbox pelo W3C (link em inglês) oferecem ainda mais detalhes para os que ousam desbravar seus densos textos. Vá em frente e construa alguns layouts. Aproveite!

Partes do tutorial foram baseadas em um guia de Stephen Hay, que concordou em licenciar seu trabalho via Creative Commons.

Comments

0