Um tutorial amigável sobre posicionamento estático, relativo, absoluto e fixo
O “posicionamento estático” refere-se ao fluxo padrão da página que
estivemos trabalhando até o momento. Os esquemas de layout
Modelo de Caixa CSS,
Floats, e
Flexbox operam nesse fluxo
"estático", mas esse não é o único esquema de posicionamento
disponível no CSS.
Os outros três tipos de posicionamento são “relativo”, “absoluto”, e
“fixo”. Cada um deles permite que você posicione manualmente
elementos utilizando coordenadas específicas, ao contrário das
opções semânticas do flexbox e floats. Ao invés de dizer “Coloque
essa caixa no centro do seu contêiner”, o posicionamento avançado
permite dizer coisas como “Coloque aquela caixa 20 píxels acima e
50 pixels à direita da origem de seu elemento pai.”
A grande maioria dos elementos em uma página web deveriam ser
dispostos de acordo com o fluxo estático da página. Estes outros
esquemas de posicionamento entram em jogo quando você quer fazer
coisas mais avançadas como ajustar a posição de um elemento particular
ou animar um componente da interface do usuário sem bagunçar os
elementos ao redor.
Este capítulo é dividido em duas partes. Começaremos examinando
posicionamento relativo, absoluto e fixo isoladamente, e então
aplicaremos tudo que aprendemos em um bonito menu dropdown.
Setup
Comece criando um novo
projeto no Atom
chamado advanced-positioning e um novo arquivo chamado
schemes.html com o seguinte cógigo:
Nós temos três exemplos para trabalhar, todos com exatamente a mesma
estrutura HTML. Alterar o comportamento de posicionamento dentro de
cada um tem efeitos dramaticamente diferentes.
Essa página depende de algumas imagens para
deixar nosso exemplo um pouco mais claro. Mantenha a pasta pai das
images no seu projeto ao descompactar os arquivos
para o seu projeto, como mostrado acima. Assegure-se de criar um
styles.css e preenchê-lo com a base necessária de
estilos, assim como:
Nada novo aqui, apenas algumas técnicas já conhecidas de
flexbox para criar uma grade
de itens. A única coisa estranha é a propriedade height
explícita no elemento <body>, que nos permitirá
rolar a página para demonstrar diferentes comportamentos de
posicionamento.
Elementos Posicionais
A propriedade position do CSS permite alterar o
esquema de posicionamento de um elemento particular. Seu valor
padrão, como você pode imaginar, é static. Quando a
propriedade position de um elemento não tem o
valor static, é chamado de "elemento posicionado".
Elementos posicionados são o tema desse capítulo inteiro.
É possível misturar e combinar diferentes esquemas de
posicionamento. Novamente, a maior parte da sua página web deve
ser estaticamente posicionada, mas é comum encontrar elementos
relativamente e absolutamente posicionados dentro de outros
elementos que são parte do fluxo normal da página.
Posicionamento Relativo
O “posicionamento relativo” move os elementos ao redor de forma
relativa à onde apareceriam normalmente no fluxo
estático da página. Isso é útil quando precisamos empurrar caixas
ao redor do fluxo padrão quando ele está um pouco fora do lugar.
Vamos transformar o elemento .item-relative no
schemes.html em um elemento posicionado
relativamente. Adicione a seguinte regra ao
styles.css:
A linha position: relative; faz dele um elemento
posicionado, e as propriedades top e left
permitem definir o quanto ele fica deslocado de sua posição estática.
É quase como definir uma coordenada (x, y) para o
elemento.
Posicionamento relativo funciona de forma similar às margens, com
uma diferença bem importante: nenhum dos elementos ao redor ou os
elementos pais são afetados pelos valores de top e
left. Todo o resto vai ser renderizado como se o
.item-relative estivesse na sua posição original.
Imagine que o deslocamento está sendo aplicado depois que
o navegador terminou de carregar a página.
As medidas das propriedades top e left da
são aplicadas a partir da direção direita e esquerda da caixa
original, respectivamente. Podemos também fazer o deslocamento
relativo com relação aos lados das propriedades bottom e
right.
Por exemplo, o código a seguir vai arrastar a caixa na direção
oposta:
Essas propriedades também aceitam valores negativos, o que
significa que existem duas formas de especificar o mesmo
deslocamento. Podemos utilizar top: -30px; no
lugar de bottom: 30px; na declaração anterior.
Posicionamento absoluto
“Posicionamento absoluto” é quase igual ao posicionamento relativo,
exceto que o deslocamento relativo é aplicado em relação
a janela do navegador, ao invés da posição original do elemento.
Já que não tem mais nenhuma relação com o fluxo estático da página,
considere isso como a forma mais manual de posicionar um elemento.
Vamos dar uma olhada em como fica adicionando a seguinte regra na
nossa folha:
Nossa estrutura HTML é exatamente igual ao exemplo anterior, no
entanto isso fará com que imagem roxa fique posicionada no canto
superior-esquerdo da janela do navegador. Você também pode tentar
definir um valor bottom ou right para
ter uma ideia melhor do que está acontecendo.
O outro efeito interessante do posicionamento absoluto
é que ele remove completamente um elemento do fluxo normal da
página. Isso é fácil de ver com os elementos alinhados à esquerda,
então vamos mudar temporariamente a propriedade
justify-content na nossa regra .example:
No nosso exemplo de posicionamento relativo (a primeira linha),
ainda tem um espaço onde o elemento posicionado costumava ficar,
mas com o posicionamento absoluto, esse espaço some! É como se o
.item-absolute nunca tivesse existido para o seu
elemento pai e os elementos ao redor dele. Mude novamente a
propriedade justify-content para space-around
antes de continuar.
Este comportamento não é tão útil na maioria das vezes por que isso
que significa que tudo na nossa página precisa estar
com um posicionamento absoluto—sendo assim, teríamos
sobreposições de elementos estáticos sobre elementos absolutos.
Então, por que a propriedade absolute existe?
Posicionamento (relativamente) absoluto
Posicionamento absoluto é muito prático quando ele é relativo a
algum outro elemento que está no fluxo estático da página.
Felizmente, existe uma forma de mudar as coordenadas do sistema de
um elemento de posicionamento absoluto.
Coordenadas para elementos absolutos são sempre relativas ao
posicionamento do elemento contêiner mais próximo, que é um elemento
posicionado. Só volta a ser relativo ao navegador quando nenhum dos
seus predecessores são posicionados. Então, se mudarmos o elemento
pai de .item-absolute para posicionamento relativo, ele
deve aparecer no canto superior-esquerdo daquele elemento
ao invés da janela do navegador.
.absolute {
position: relative;
}
A div.absolute está posta no fluxo normal da
página, e nós podemos movê-la manualmente ao redor do
.item-absolute da forma como quisermos. Isso é ótimo,
porque se quisermos alterar o fluxo normal do contêiner, vamos dizer
para um layout mobile, qualquer elemento com posicionamento
absoluto irá se mover automativamente.
Perceba que nós não especificamos nenhuma coordenada de deslocamento
para a classe .absolute. Estamos utilizando
posicionamento relativo com um único propósito de deixar nosso
elemento absoluto encaixar de novo no fluxo normal da página. É
assim que combinamos posicionamento absoluto com estático.
Posicionamento fixo
“Posicionamento fixo” tem muito em comum com posicionamento
absoluto: é bem manual, o elemento é tirado do fluxo normal da
página, e o sistema de coordenadas é relativo a toda a janela do
navegador. E diferença é que elementos fixos não rolam junto com o
resto da página.
Isso irá colocar a imagem vermelha no canto inferior-direito da
janela. Tente rolar a página, e você irá descobrir que ele não se
move com o resto dos elementos da página, enquanto a imagem roxa
com o posicionamento absoluto sim.
Isso irá permitir que você crie barras de navegação que sempre
estarão apresentadas na janela como aqueles baners chatíssimos que
nunca somem.
Posicionamento de elementos para animações
Isso está um pouco fora do escopo, já que esse tutorial é sobre HTML
e CSS, não JavaScript. No entanto, animações são um dos primeiros
usos para posicionamento relativo e absoluto, então vamos dar uma
olhadinha nisso para animar um dos nosso elementos.
Esses esquemas avanaçados de posicionamento permitem que o
JavaScript movimente os elementos pela página enquanto evitamos
qualquer tipo de interação com os elementos ao redor. Por exemplo,
vamos copiar e colar o código abaixo no nosso
schemes.html depois do terceiro elemento
.container. O elemento <script> deve
ser a última coisa dentro do <body>.
<script>var left = 0;
functionframe() {
var element = document.querySelector('.item-relative');
left += 2;
element.style.left = left + 'px';
if (left >= 300) {
clearInterval(id)
}
}
var id = setInterval(frame, 10)
</script>
Esse código em JavaScript cria uma animação simples que fica
atualizando a propriedade left do
.item-relative. Quando você atualizar a página,
deve ver a imagem em azul flutuando para o canto direito do
contêiner.
Esse é um exemplo bem rudimentar, mas com sorte verá como é
aplicável para animações bonitinhas. Se você tentasse alcançar o
mesmo efeito manipulando as propriedades de margem ou
o preenchimento, você poderia mover sem querer as
caixas posicionadas estaticamente e/ou também o elemento
.exemple.
Elementos posicionados para menus
Certo, essas são todas as técnicas. Vamos fazer alguma coisa
avançado com elas! O resto desse capítulo é para aplicar
nossas novas habilidades criando um menu bem lindão de navegação
com uma interação de rolagem para os links. Vamos contruir
essa página desde
o começo.
Posicionamento fixos vão permitir que o menu fique na parte superior
da página, e o posicionamento relativo vai nos dar uma âncora para
o posicionamento absoluto da rolagem (dropdown). Também
falaremos sobre as melhores práticas para menu de navegação e ver
alguns usos práticos para
pseudo-classes, falamos sobre iso em Seletores CSS.
Para começar vamos precisar de uma página nova, chamada
menu.html que tem um cabeçalho e um menu na parte
superior:
Menus de navegação devem ser quase sempre marcados como uma
lista <ul> ao invés de um monte de elementos
<div>. Essas semânticas tornam a navegação na
sua página muito mais acessível para mecanismos de busca. Perceba
também como estamos preparando nosso menu dropdown
adicionando um atributo class no primeiro ítem
<li> da lista. O <span>
irá permitir diferenciar o rótulo revelado no submenu.
Próximo, precisamos de uma nova folha de estilo chamada
menu.css que fará nosso .header parecer
um pouco mais como um cabeçalho de verdade, entre outras coisas:
Isso tudo deve ser familiar pra você, mas note o posicionamento
fixed do .header, que irá manter nosso
menu de navegação sobre qualquer conteúdo que tivermos na página.
Itens de menu em linha
Apesar da marcação como uma lista não ordenada, o menu de navegação
da maioria das páginas web não se parece como uma lista. Podemos
arrumar isso transformando a lista de itens em
caixas em linha
ao invés de caixas em bloco, através da propriedade display.
Adicione o código abaixo no menu.css:
Precisamos utilizar
seletores filhos aqui ao invés de
seletores descendentes
porque nós só queremos selecionar o elemento
<li> que está dentro do .menu. Isso
se faz importante uma vez que adicionamos nosso submenu, que tem seu
próprio elemento <li> que não queremos estilizar
com essa regra. Este trecho também adiciona margens em todos os
nossos itens, mas é remove do último <li> ao
utilizar a pseudo-classe :last-of-type. Essa é uma
técnica bem comum para criar margens entre os itens.
Submenus
Nosso submenu está se parecendo como o nosso menu, exceto por
todas as coisas que estão aninhadas dentro da lista de item.
Altere o elemento .menu para casar com o que está
abaixo, garantindo que a lista .features-menu esteja
encapsulada no primeiro <li> do elemento
.menu.
<ulclass='menu'><liclass='dropdown'><span>Recursos ▾</span><ulclass='features-menu'><!-- Início do submenu --><li><ahref='#'>Harder</a></li><li><ahref='#'>Better</a></li><li><ahref='#'>Faster</a></li><li><ahref='#'>Stronger</a></li></ul><!-- Fim do submenu --></li><li><ahref='#'>Blog</a></li><!-- Isso continua o mesmo --><li><ahref='#'>Assinar</a></li><li><ahref='#'>Sobre</a></li></ul>
Isso irá providenciar muitas informações para mecanismos de
pesquisa. Permite que o Google veja que todos esses novos itens
estão associados com um rótulo Recursos e
que ele s formam uma seção isolada da nossa página web. Você deve
sempre marcar menus de navegação complexos como esse com esse
tipo de estrutura.
Quanto a CSS, vamos lidar com a interatividade da parte da rolagem
depois. Agora vamos só fazer o submenu se parecer do jeito que
queremos. Adicione um estilo simples para que possamos ver a caixa
que estamos tentando posicionar:
O submenu em si já está corretamente estilizado, mas está sendo
apresentado no lugar errado, e está modificando todo o resto do
nosso menu. Isso deveria ser esperado porque ele ainda está
posicionado estaticamente, o que significa que ainda está se
comportando como seu pai e os elementos ao redor dele.
Para criar o layout desejado, precisamos chamar nossas novas
habilidades de posicionamento com CSS.
Submenus (relativamente) absolutos
Nós queremos que nossos outros ítens do menu principal sejam
apresentados como estavam antes de adicionarmos o submenu, como se
o submenu nem estivesse ali. Pera aí…isso é exatamente o
comportamento de elementos com posicionamento absoluto. Vamos ver como
isso vai ser. Adicione as linhas abaixo a regra
.feature-menu:
Perfeito! Agora o submenu não é mais parte do fluxo estático da
página, assim os ítens do menu principal voltaram ao normal. No
entanto, o submenu está aparecendo por baixo do rótulo
Recursos—não no canto da janela do navegador.
Que coincidência…nós acabamos de aprender como fazer isso!
O submenu está declarado como um item
<li class='dropdown'>. Se transformarmos isso
em um elemento posicionado isso deve mudar o sistema de
coordenadas utilizada pelo posicionamento absoluto do
.features-menu:
.dropdown {
position: relative;
}
Beleza, próximo problema. Nosso submenu está no lado direito, mas
agora ele está cobrindo o rótudo dos Recursos.
Z-Index
Não tínhamos lidado com problemas de “profundidade” antes. Até
agora, todo nossos elementos HTML eram renderizados acima ou abaixo
um dos outros, é a forma mais intuitiva. Mas, agora que estamos
trabalhando com configurações mais avançadas, depende do navegador
determinar quais elementos aparecem um sobre o outro sem escondê-los.
A propriedade z-index vai permitir o controle da
profundidade dos elementos na página. Se você imaginar a sua tela
(do computador, smartphone, etc.) como um espaço 3D,
valores negativos do z-index vão mais para o fundo da
página, e valores positivos vem mais para a superfície da página.
Em outras palavras, os elementos de .features-menu
precisam ter valores menores de z-index que o rótulo
Recursos. O valor padrão do z-index
é 0, então vamos deixar ambos com valores maiores que
isso. Felizmente nós encapsulamos o rótulo Recursos
em um <span>, permitindo a estilização dele via
seletore filhos, da seguinte forma:
O rótulo Recursos deve aparecer agora em cima do
submenu. Preste atenção na linha position: relative;.
Isso é preciso, por que somente elementos posicionados são
afetados pela propriedade z-index. Isso é fácil de
esquecer, então crie uma nota mental para a próxima vez que você
tiver problemas de profundidade e as regras CSS não tiverem
nenhum efeito.
Utilizamos uma propriedade chamada cursor para fazer
parecer como se fosse um link quando o usuário passar com o ponteiro
do mouse por cima do rótulo. Você pode ler um pouco mais
sobre essa propriedade na
Mozilla Developer Network.
Pseudo-Classes para menus rolantes
Tudo certo! Nosso submenu está pronto! Nossa tarefa final é
escondê-lo até que o usuário passe o mouse sobre ele.
Lembra da
pseudo-classe :hover do capítulo Seletores CSS? Nós podemo utilizá-la para
adicionar uma interação de rolagem (dropdown) no submenu.
Primeiro, precisamos mudar nossa regra .features-menu
para aparecer somente quando o usuário pousar o mouse
sobre ele adicionando o seletor descendente :hover.
Modifique o seletor .features-menu para ficar como
abaixo:
.dropdown:hover.features-menu { /* Isso costumava ser o `.features-menu` */display: flex; /* Deixe todo o resto como está */flex-direction: column;
background: #B2D6FF;
/* ... */
}
Depois, precisamos inicialmente esconder o submenu utilizando a
propriedade display. Adicione essa nova regra à folha
menu.css:
.features-menu { /* Adicione isso como uma nova regra */display: none;
}
Configurando o display como none vai
fazer o elemento desaperecer completamente. Ao sobreescrever
aquele valor com flex na regra :hover,
estaremos efetivamente dizendo ao navegador para mostrar o
.features-menu de novo. Essa é uma maneira inteligente
de combinar seletores descendentes e pseudo-classes que permita
esconder ou mostrar um elemento de forma condicional.
Resumo
Neste capítulo, demos uma olhada em quatro novos esquemas de layout CSS:
Relativo
Absoluto
Relativamente absoluto
Fixo
Utilizamos o posicionamento relativo para ajustar a posição de um
elemento sem afetar as caixas ao redor. O posicionamento absoluto
tirou o elemento do fluxo estático da página e o colocou em uma
posição relativa a janela do navegador, enquanto o relativamente
absoluto nos permite colocar ele novamente no fluxo estático da
página. E finalmente, o posicionamento fixo nos permite ficar um
elemento em uma posição e não rolar ela junto com o resto da página.
Utilizamos essas novas técnicas de posicionamento para criar
um menu de navegação bem sofisticado. Se você achou complicado,
é por que ele é! Mas não se preocupe, você não precisa se sentir
pressionado para memorizar a HTML e a CSS por trás do
nosso menu. Seu objetivo deve ser ter a habilidade de usar esse
exemplo como referência daqui três meses e entender tudo o que
é tudo isso de position: relative; e
position: absolute; e o que essas declarações
estão fazendo.
Esse menu também é um exemplo de como uma marcação HTML inicial
pode tornar nossa vida mais fácil. Primeiro, criamos a estrutura
semântica que queríamos. Depois, escrevemos algumas regras
CSS para colocar as caixas exatamente onde queríamos. Sempre que
você se deparar com um modelo que parece complicado e você não souber
como começar, essa é uma boa forma de abordar o problema.
Ainda temos um problema com o nosso menu: ele não foi construído
pensando em dispositivos móveis. Smartphones e
tablets não tem uma forma de pousar o ponteiro sobre uma
parte da página, e nosso layout não se ajusta quando a janela é
menor do que 960 pixels. Essa página precisa de um pouco da mágica
do JavaScript (ou uma CSS realmente avançada), então vamos
deixar isso para outro tutorial. Mas, vamos poder resolver o último
problema com um design responsivo no próximo capítulo.