Pare de chutar e aprenda como funciona a position: absolute
Essa foi a propriedade que eu mais utilizei no meu primeiro ano como Desenvolvedor FrontEnd. Até hoje me lembro do dia que fiz o código de uma landing page para o dia das mães na Locaweb e depois de uma semana trabalhando nela eu entreguei. Nessa época por algum motivo eu não tinha mais ninguém no mesmo time que eu como dev FrontEnd, mas logo a 4 fileiras a minha frente habitava um dev com um bom coração feliz, que me fez jogar fora todo o trabalho de uma semana que estava cheio de position: absolute. Em apenas uma noite fizemos a landing page juntos usando direito todas as propriedades de posicionamento do CSS, como: display: inline; display: block; display: inline-block; float: left | right; postion: static | relative.
Hoje graças ao William Bruno que foi o dev com o bom coração feliz, eu consigo passar todo meu conhecimento nas aulas da Caelum de FrontEnd, obrigado man. ;-)
Antes de entender o nosso desafio vamos ver o HTML e CSS base que utilizaremos:
HTML (index.html)
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8"><title>Exemplo de como funciona a postion: absolute</title><link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/position.css">
</head>
<body>
<div class="elementExample elementExample_first">
Apenas uma div
</div>
<div class="elementExample elementExample_second">
Apenas outra div
</div>
<div class="elementExample elementExample_last">
<div class="elementExample-internal">Interna</div>
</div>
</body>
</html>
CSS (position.css)
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
background-color: #6c5ce7;
}
.elementExample_second {
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
CSS (reset.css)
* {
margin: 0;
padding: 0;
border: 0;
}
body {
background-color: #b2bec3;
font-family: "Open Sans", sans-serif;
}
ul, ol, li {
list-style: none;
}
Por favor abra o arquivo index.html
no seu browser (navegador) e você verá o seguinte resultado:
Agora que já temos o nosso layout inicial, podemos falar do nosso objetivo até o final do post. Vamos deixar a última div
que é a vermelha alinhada totalmente a esquerda e no topo da página, além disso o elemento que está dentro dela tem que ficar centralizado. Nossa segunda div
que é a verde escuro, ficará centralizada em relação à tela, tanto no sentido vertical quanto horizontal. Por último deixamos a nossa primeira div
que é a roxa, totalmente no lado direito do browser e no topo. Conforme a imagem a seguir:
Vamos começar a implementar nosso objetivo pela nossa primeira div
, a roxa. Primeiro tentando deslocar ela para o lado direito da tela. Para isso precisamos voltar no nosso arquivo position.css
e adicionar a propriedade position
com o valor absolute
no seletor .elementExample_first
:
postion.css
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute; /* adicionamos essa linha */
background-color: #6c5ce7;
}
.elementExample_second {
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Indo até o browser e atualizando ele, você verá o seguinte resultado visual:
Agora temos a nossa primeira div
e a terceira na tela, mas parece que a nossa segunda div
sumiu. :-(
Isso está acontecendo porque toda vez que utilizamos a propriedade position
com o valor absolute
, esse valor cria de imediato um novo contexto para a div
e este contexto fica a frente do contexto do browser, além disso, é liberado o espaço que a primeira div
ocupava no contexto do browser. Por causa desse último comportamento do absolute
que não estamos conseguindo ver a nossa segunda div
, portanto podemos concluir que a segunda div
está abaixo da nossa primeira div
. Para vermos se isso é verdade, vamos voltar para o nosso arquivo position.css
e adicionar em nossa primeira div
a propriedade opacity
com o valor 0
que deixará ela totalmente transparente.
position.css
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute;
opacity: 0; /* adicionamos essa linha */
background-color: #6c5ce7;
}
.elementExample_second {
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Voltando no browser e atualizando ele, você verá que a nossa segunda div
está de fato atrás da primeira div
(que neste momento está transparente):
Para mover a nossa primeira div
para o lado direito do browser só precisamos adicionar a propriedade right
com o valor 0
. Ah! não podemos nos esquecer de remover a propriedade opacity
. Vamos até o arquivo position.css
para fazer essas alterações:
position.css
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute;
right: 0; /* adicionamos essa linha e removemos a propriedade opacity*/
background-color: #6c5ce7;
}
.elementExample_second {
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Salvando o arquivo e voltando para o nosso browser (lembre-se de atualizar) podemos ver que conseguimos implementar a primeira parte do nosso objetivo:
Não temos só a propriedade right
temos um total de quatro propriedades que podemos utilizar junto com a propriedade position
, uma vez que o valor dela não é o padrão static
. As quatro propriedades são: right
, bottom
, left
e top
.
Quando utilizamos apropriedade right: 0;
em conjunto com a propriedade position: absolute;
na nossa primeira div
ela foi para o ponto 0 do lado direito do browser. Então podemos concluir que a referência é o browser uma vez que estamos utilizando o valor absolute
para a nossa propriedade position
. Fora algumas linhas a seguir que temos apenas uma exceção. ;-)
Agora vamos fazer o código que deixará a segunda div
centralizada no browser tanto no sentido horizontal (eixo x) quando no sentido vertical (eixo y). Como acabamos de ver, se quisermos alinhar um elemento em relação ao browser podemos utilizar a propriedade position
com a valor absolute
, portanto vamos ao nosso arquivo position.css
para adicionar no seletor de classe .elementExample_second
o valor absolute
pra propriedade position
:
position.css
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute;
right: 0;
background-color: #6c5ce7;
}
.elementExample_second {
position: absolute; /* adicionando essa linha */
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Indo até o browser e atualizando ele podemos ver um comportamento de criar um novo contexto a frente do contexto padrão do browser acontecendo novamente:
A primeira coisa que quero fazer junto com você, é centralizar o elemento no sentido horizontal (eixo x). Para isso podemos utilizar a propriedade left
com o valor 50%
, essa porcentagem pega como referência a largura do browser, por exemplo se o eu browser tiver com a largura de 1000px o 50%
será a mesma coisa que 500px, mas como a porcentagem é uma unidade de medida relativa não vamos precisar se preocupar caso alargura do browser seja alterada pelo usuário.
Bora ir no nosso arquivo position.css
no seletor .elementExample_second
e adicionar nele a left: 50%;
:
position.css
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute;
right: 0;
background-color: #6c5ce7;
}
.elementExample_second {
position: absolute;
left: 50%; /* adicionando essa linha */
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Atualizando o browser teremos o seguinte resultado visual:
Eita! Não ficou centralizada a nossa div
como o esperado. Na verdade o que está centralizado é o lado esquerdo do elemento porque o position: absolute;
utiliza como referência o lado esquerdo da div
não o centro dela uma vez que utilizamos a propriedade left
, se mudarmos para a propriedade right
a referência se torna o lado direito da div
.
O que precisamos fazer para que a div
fique de fato centralizada é mover exatamente a metade da largura da div
para o lado esquerdo. Para isso temos a propriedade transform
com o valor translateX
que move o elemento para direita se passarmos um valor positivo e se passarmos um valor negativo movemos ela para a esquerda, sempre trabalhando com o sentido horizontal (eixo X).
Como precisamos mover metade da largura da div
, que é de 200px, moveremos então 100px e, este valor tem que ser negativo para que ela seja movida para a esquerda.
Se colocarmos o valor em px
toda vez que mudarmos a largura da div
será necessário alterar também o valor que acabamos de definir no translateX
. Para deixar o código com uma manutenção mais feliz, podemos utilizar no lugar do -100px o valor de -50% e esse -50% será sempre a metade da largura que a div
tem.
Vamos voltar no nosso arquivo position.css
e adicionar o transform: translateX(-50%);
e ver se conseguimos chegar no resultado esperado de deixar a nossa segunda div
centralizada no sentido horizontal (eixo x):
position.css
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute;
right: 0;
background-color: #6c5ce7;
}
.elementExample_second {
position: absolute;
left: 50%;
transform: translateX(-50%); /* adicionado essa linha */
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Dessa vez se você for até o browser teremos o resultado esperado:
Agora precisamos aplicar o mesmo conceito que fizemos no sentido horizontal (eixo x) e aplicar no sentido vertical (eixo y). Vamos adicionar primeiro a propriedade top
com valor de 50%
no seletor .elementExample_second
que está no arquivo position.css
:
position.css
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute;
right: 0;
background-color: #6c5ce7;
}
.elementExample_second {
position: absolute;
left: 50%;
top: 50%; /* adicionado essa linha */
transform: translateX(-50%);
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Após salvar o arquivo position.css
, vá até o seu browser e atualize ele, você terá o seguinte resultado visual:
Tivemos o mesmo efeito de quando utilizamos o left: 50%
, agora com o top: 50%
a nossa div
não está centralizada novamente, na verdade o que está centralizado é a parte do topo dela em relação a página, por isso que precisamos acrescentar na propriedade transform
o valor translateY(-50%)
para mover o elemento a metade da altura dele para cima. Volte ao arquivo position.css
e adicione mais um valor para a propriedade transform
que criamos no seletor .elementExample
, o valor será translateY(-50%)
:
position.css
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute;
right: 0;
background-color: #6c5ce7;
}
.elementExample_second {
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%); /* adicionamos o valor translateY(-50%) */
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Agora sim! Indo até o browser você verá que conseguimos implementar a segunda parte do nosso objetivo:
Nessa terceira e última parte do nosso objetivo só precisamos centralizar a div
interna, mas dessa vez não em relação a página mas em relação a div
vermelha que é o elemento pai da div
interna. Para isso podemos utilizar as mesmas propriedades que utilizamos para centralizar a segunda div
. Por tanto, precisamos voltar ao arquivo position.css
e no seletor .elementExample-internal
adicionar as 4 propriedades que utilizamos pra centralizar a nossa segunda div
:
position.css
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute;
right: 0;
background-color: #6c5ce7;
}
.elementExample_second {
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
position: absolute; /* adicionamos essa linha e as 3 seguintes */
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Indo até o browser, não teremos o comportamento que queremos em nosso objetivo, mas felizmente é o comportamento esperado. Lembre-se que o absolute
pega como referência o browser, sendo assim o elemento interno também ficará no centro do browser, conforme a imagem a seguir:
Felizmente temos mais uma regra no absolute
que nos ajudará a executar o nosso objetivo. Para fazer com que a div
interna respeite o seu pai deixando de vazar o tamanho dele, precisamos definir um position
diferente de static
para o pai do elemento que está com o position: absolute
. O valor mais utilizado para o position
no pai é relative
porque essa propriedade apesar de criar um novo contexto, não libera o espaço dela no contexto do browser, dessa forma fica mais fácil prever o que acontecerá no layout.
Pra colocar em prática a teoria acima, vamos aplicar a position: relative
na div
vermelha que tem classe elementExample_last
:
.elementExample {
width: 200px;
height: 200px;
line-height: 200px;
color: #FFF;
text-transform: uppercase;
text-align: center;
cursor: pointer;
}.elementExample_first {
position: absolute;
right: 0;
background-color: #6c5ce7;
}
.elementExample_second {
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
background-color: #00b894;
}
.elementExample_last {
background-color: #d63031;
}.elementExample-internal {
position: absolute; /* adicionamos essa linha */
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);width: 100px;
height: 100px;
line-height: 100px;
background-color: #00cec9;
}
Voltando ao browser podemos ver que nosso objetivo está completo:
Se ficou qualquer dúvida e tem qualquer sugestão para melhorar nesse post e nos demais, por favor não deixe de falar nos comentários ou se preferir você pode me adicionar nas redes socias da vida, você me achará por MarcoBrunoBR tanto no twitter, facebook ou linkedin. Eu também gosto de usar um chat chamado Telegram, lá você também me achará por MarcoBrunoBR.
Até o próximo post :-)