Exercícios

percebendo a propriedade float em CSS

artigo original

De cada vez que vimos um artigo numa revista, onde uma imagem posicionada à esquerda ou à direita da página parece flutuar no meio do texto, estamos a ver um exemplo do resultado da propriedade float adaptada ao mundo da impressão.

a definição

Vamos começar com a definição de float de acordo com o W3C (World Wide Web Consortium):

"A float is a box that is shifted to the left or right on the current line. The most interesting characteristic of a float (or "floated" or "floating" box) is that content may flow along its side (or be prohibited from doing so by the "clear" property); Content flows down the right side of a left-floated box and down the left side of a right-floated box."

Existem quatro valores possíveis para aplicar à propriedade float: left, right, inherit e none;
Cada valor é só por si relativamente explicativo.
Por exemplo, se atribuirmos float: left a um elemento, ele irá posicionar-se no limite esquerdo do elemento pai; A mesma ideia se aplica se atribuirmos float: right a um elemento, ele posicionar-se-á no limite direito do elemento pai; O valor inherit diz a um elemento para herdar o valor da propriedade float do elemento pai.
O valor da propriedade por defeito é none e diz ao elemento para não flutuar e reger-se pelo fluxo normal do documento.

exemplo A
	
img { float: right; margin: 10px; }
	

O fluxo normal do documento faz com que cada block element (div, p, h1, etc.) se empilhe em cima de outro verticalmente, do topo do viewport para baixo. Os elemento flutuantes são primeiramente colocados na página de acordo com o fluxo normal do documento, depois são retirados desse fluxo e reposicionados à esquerda ou à direita do elemento pai dependendo do valor aplicado à propriedade.

Vamos ver mais um exemplo. No exemplo B existem três blocos sem qualquer valor atribuído à propriedade float:

	
.block { width: 200px; height: 200px; }
.pink  { background-color: #ee3e64; }
.blue  { background-color: #44accf; }
.green { background-color: #b7d84b; }
	

Repare como se posicionam uns em cima dos outros. É este o conceito do fluxo normal do documento.
Eis o mesmo exemplo mas agora com a aplicação da propriedade float exemplo C a todos os elementos.

	
.block { float: left; width: 200px; height: 200px; }
	

O que sucederá se o espaço disponível não for suficiente para mostrar todos os blocos?
Vamos partir do exemplo anterior e acrescentar dois blocos. Agora experimente redimensionar a janela do browser e repare como os blocos se ajustam ao espaço existente exemplo D.

a utilização de clear

Como se deve recordar, um elemento a que se aplicou a propriedade float é primeiramente colocado segundo o fluxo normal do documento e depois removido desse fluxo de acordo com o valor da propriedade. Isto significa que o comportamento dos elementos que se seguem é imprevisivel.
No exemplo E, existem dois blocos (rosa e azul) a que foi atribuído o valor left à propriedade float, logo a seguir e sem qualquer valor na propriedade float mais dois blocos (verde e laranja). Eis o HTML e o CSS para o exemplo E:

	
<div class="block pink float"></div>
<div class="block blue float"></div>
<div class="block green"></div>
<div class="block orange"></div>
<div class="block purple"></div>

.block {
  width:  200px;
  height: 200px;
}

.float	{ float: left; }
.pink	{ background-color: pink; }
.blue	{ background-color: blue; }
.green	{ background-color: green; }
.orange { background-color: orange; }
.purple { background-color: purple; }
	

O que se passa com o bloco verde? Apesar de não se ver, na verdade ele está lá, escondido debaixo do bloco rosa.
O comportamento do bloco rosa e do bloco azul é prevísivel, encontram-se lado a lado, ambos a flutuar à esquerda do elemento pai. O que se passa é que ao atribuirmos valores à propriedade float os elementos são removidos do fluxo normal e agora ambos os blocos (verde e laranja) se posicionam como se os outros não existissem. É por isso que o bloco verde se esconde por debaixo do bloco rosa.

Para fazer aparecer o bloco escondido precisamos de utilizar a propriedade clear.

Existem cinco valores possíveis para a propriedade clear: left, right, both, inherit, e none.

A atribuição do valor left indica que o topo desse elemento deve encostar por debaixo de qualquer elemento que tenha o valor left atribuído à propriedade float. O mesmo conceito se aplica para o valor right, o elemento deve encostar por debaixo de qualquer elemento que tenha o valor right atribuído à propriedade float. A atribuição do valor both indica ao elemento que o topo deve posicionar-se por debaixo de qualquer elemento que tenha o valor left ou right atribuído à propriedade float. O valor inherit utiliza o valor da propriedade clear do elemento pai, enquanto que o valor, por defeito, none comporta-se como esperado. Munidos deste conhecimento, olhemos para o exemplo E2.

Desta vez vamos aplicar a propriedade clear ao bloco verde com a intenção de interromper a sequência de floats e fazê-lo voltar ao fluxo normal do documento. O código ligeiramente alterado ficará assim:

	
<div class="block pink float"></div>
<div class="block blue float"></div>
<div class="block green clear"></div>
<div class="block orange"></div>

.block {
  width: 200px;
  height: 200px;
}
.float	{ float: left; }
.clear	{ clear: left; }
.pink	{ background-color: #ee3e64; }
.blue	{ background-color: #44accf; }
.green	{ background-color: #b7d84b; }
.orange { background-color: #E2A741; }
	

Ao atribuirmos clear: left ao bloco verde, dissemos-lhe para agir como se o bloco rosa estivesse no fluxo normal do nosso documento, apesar de removido e posicionar-se por debaixo dele. Esta propriedade é extremamente poderosa; como se pode ver, permite trazer os elementos não flutuantes para o fluxo normal, um comportamento esperado por defeito.

utilizando floats em layouts

Vamos observar um exemplo simples: um website com duas colunas, a área de conteúdos à esquerda, navegação à direita e delimitados por um header e um footer. Para o bem do presente artigo, vamos só olhar o código relacionado com os elementos flutuantes.
Eis o exemplo F.

	
#container {
	width: 960px;
	margin: 0 auto;
}

#content {
	float: left;
	width: 660px;
	background-color: #fff;
}

#navigation {
	float: right;
	width: 300px;
	background-color: #eee;
}

#footer {
	clear: both;
	background-color: #aaa;
	padding: 10px;
}
	

Analisemos o que se está a passar. O elemento que irá conter todos os outros elementos chama-se #container, será ele o responsável por mantê-los nos respetivos lugares. Sem ele, os elementos flutuantes sairiam disparados para o canto mais à esquerda e mais à direita do viewport (a janela do browser).

Temos em seguida os elementos #content e #navigation, são elementos a quem foi atríbuído um valor à propriedade float; #content flutua do lado esquerdo e #navigation do lado direito, temos assim um layout de duas colunas. Foi definido um valor para a largura de cada um deles de forma a preencherem totalmente o elemento onde estão inseridos.

Finalmente temos o #footer, aqui foi atribuído valor à propriedade clear. Como sabemos esta propriedade tráz de volta ao fluxo normal qualquer elemento a seguir do documento

O que teria acontecido se nos tivessemos esquecido de atribuir um valor à propriedade clear? Dê uma olhadela ao exemplo G

O nosso #footer teria deslizado para debaixo do elemento #navigation. Isto teria acontecido porque ainda existe espaço por preencher por debaixo do elemento #navigation, este é aliás o comportamento correto.

Infelizmente não é o tipo de comportamento que esperaríamos neste momento. É possível ver agora o tipo de interação existente entre as propriedades clear e float e de que forma se complementam tão bem.

float first

Até agora, vimos alguns exemplos bastante simples e que não criam muitas dores de cabeça. Há, entretanto, alguns pormenores que devemos ter em atenção ao trabalhar com a propriedade float. Surpreendentemente, uma dos maiores problemas não é com o CSS, mas sim com o próprio HTML.

O sítio onde é utilizada a propriedade float pode causar resultados diferentes. Dê uma olhadele no Exemplo H .

	
#container {
	width: 280px;
	margin: 0 auto;
	padding: 10px;
	background-color: #aaa;
	border: 1px solid #999;
}

img { float: right; }
	

O elemento pai #container tem menos largura mantendo assim o elemento flutuante, img, dentro dos limites. Veja a seguir o HTML:

	
<div id="container">
	<img src="image.gif" width="80" height="80" alt="imagem" >
	<p>This is some text contained within a smallish box. I'm using it as an example of how placing your floated elements in different orders in your HTML can affect your layouts. For example, take a look at this great photo placeholder that should be sitting on the right.</p>
</div>
	

Este conceito básico permite-nos obter o resultado desejado, mas e se alterarmos o HTML ligeiramente? No exemplo I a etiqueta img foi movida para depois do parágrafo de texto:

	
<div id="container">
	<p>This is some text contained within a smallish box. I'm using it as an example of how placing your floated elements in different orders in your HTML can affect your layouts. For example, take a look at this great photo placeholder that should be sitting on the right.</p>
	<img src="image.gif" width="80" height="80" alt="imagem" >
</div>
	
	
<div id="container">
	<p>This is some text contained within a small-ish box. I'm using it as an example of how placing your floated elements in different orders in your HTML can affect your layouts. For example, take a look at this great photo placeholder that should be sitting on the right.</p>
	<img src="image.gif" width="80" height="80" alt="imagem" >
	<div style="clear: right;"></div>
</div>
	
	
<div id="container">
	<img src="image.gif" width="80" height="80" alt="imagem" >
	<img src="image.gif" width="80" height="80" alt="imagem" >
	<img src="image.gif" width="80" height="80" alt="imagem" >
</div>
	
o nosso CSS fica assim:
	
#container {
	width: 260px;
	margin: 0 auto;
	padding: 10px 0 10px 10px;
	background-color: #aaa;
	border: 1px solid #999;
}

img {
	float: left;
	margin: 0 5px 0 0;
}
	
	
#container {
	overflow: hidden;
	width: 260px;
	margin: 0 auto;
	padding: 10px 0 10px 10px;
	background-color: #aaa;
	border: 1px solid #999;
}
	

O resultados estão no exemplo L.
Bastante interessante, não? Outro método com resultados semelhantes e com menos xxx utiliza o pseudo selector :after. Utilizando o nosso exemplo, o código ficaria assim:

Pretty cool right? Another method which gives similar results with fewer caveats uses the pseudo selector :after. Using our example, the code is:

	
#container:after {
	content: ".";
	display: block;
	height: 0;
	clear: both;
	visibility: hidden;
}