Não apanhe do Layout - CSS positions (parte 1)
Tags: css, patterns
Published: 2020-09-08 22:28:59

_A propriedade `position` é parte fundamental da criação de layouts CSS pois permite que você posicione livremente elementos em qualquer lugar da sua página, nesse post eu vou ensinar conceitos e padrões de design das propriedades de posição para que isso não seja mais um problema em nenhum dos seus layouts_

## O que é a propriedade `position`?
> A propriedade `position`define como um elemento pode ser posicionado (renderizado) no documento (página) - [MDN](https://developer.mozilla.org/pt-BR/docs/Web/CSS/position)

Ao atribuir essa propriedade a um elemento, uma vez definido um valor que não seja estático, você consegue mover esse elemento nas dimensões x e y da página utilizando os controles X(left, right) e Y(top, bottom). Nessa parte eu vou focar exclusivamente como funciona o cálculo da propriedade position e seus dois valores mais utilizados: `position: relative` e `position: absolute`.

> Dica 💡: Evite utilizar margens em movimentos posicionados, o valor da margem soma ao dos _position handlers_

## Qual a diferença entre relativo e absoluto?
As duas principais diferenças entre posição relativa e absoluta são:

* O que significado da posição (0, 0) do elemento posicionado.

* A posição absoluta **tira** o elemento do fluxo da página, ou seja, ele sobrepõe **todos** elementos que não foram posicionados no eixo x `z-index: <numero>;`

No caso de `relative`, a posição padrão (0, 0) é o local atual do elemento, à partir do **canto superior esquerdo dele mesmo** (lembre-se disso). Por isso que ao colocar `position: relative` o elemento não sai do lugar, pois como ele se referencia a sua própria posição, se você não o movimentar ele não sairá do lugar.

![Elemento com position relative no centro da página pois ainda não foi movimentado](https://dev-to-uploads.s3.amazonaws.com/i/k66dj06wcobgwlcgskxu.jpg)
Quando falamos de `position: absolute`, o valor padrão (0, 0) se refere ao canto superior esquerdo do primeiro elemento pai posicionado. Ou seja, o pai do seu elemento não tem nenhum position (ele é static por padrão), o elemento posicionado como "absoluto" vai procurar um pai posicionado ou seja, com uma propriedade position contendo um valor que não seja _static_.

![Elemento posicionado no canto superior esquerdo, de acordo com o elemento pai (body)](https://dev-to-uploads.s3.amazonaws.com/i/edat9dtzqpchre78h3a9.png)

E caso não encontrar nenhum pai posicionado, o elemento se posicionará de acordo com o body. Por isso que quando alguém define um elemento absoluto sem isso em mente, ele vai lá pra casa do car*!@o, deixando todo mundo traumatizado.


## OMG, quem poderá nos defender 😫? Convenções!

Dentro do HTML temos em sua maioria, tags de elementos e containers. As tags containers são:

* header
* footer
* nav
* aside
* main
* div

Desconsiderei span porque além dele ser um container não semântico, ou seja, não possuir significado contextual, ele foi feito para elementos inline, pra ser ultilizado principalmente dentro de tags de texto

Tendo isso em mente, criemos uma convenção:
> Containers - `position: relative`
> Elementos - `position: absolute`

![Código CSS mostrando como posicionar todos os containers de maneira relativa](https://dev-to-uploads.s3.amazonaws.com/i/1zysez4snhi3byazeaof.png)

Uma dificuldade que temos com elementos posicionados absolutamente é que é muito difícil ser responsivo com eles, mesmo usando unidades relativas (vw, vh, %, em, etc). Quando chega nesse ponto, algumas pessoas acabam tendo que movimentar no olho as position handlers (top, left, right, bottom).

![Elementos posicionados dentro de media queries com valores de posição decimais malucos](https://dev-to-uploads.s3.amazonaws.com/i/lks4brdv94ei3ebeoc9i.jpg)

Conseguimos posicionar esses elementos de maneira mais prática, performática e sem números mágicos usando a função `transform: translate` pelo fato de que ele move o elemento de acordo com a posição atual, independente do contexto de `position` que você esteja utilizando.

### A propriedade transform
O transform funciona porque pra propriedade `left` por exemplo, 50% diz respeito a distância do elemento à partir canto superior esquerdo do pai. Para o transform, 50% diz respeito a largura do próprio elemento, ou seja, se fossemos calcular a relação entre trnaslateX e leftm seria algo assim:

posleft + larguraEl - larguraEl * .5

onde:
* **posLeft** é o valor que o elemento se movimenta à partir do lado esquerdo do pai

* **larguraEl** é a largura do elemento

* **larguraEl * .5** é o valor de `translateX(-50%) que move o elemento para esquerda em 50% da sua largura


Image
Image
Isso significa que o elemento não está só centralizado, mas que também o plano cartesiano da página não é orientado mais pelo canto superior esquerdo, mas pelo centro, permitindo você movimentar o elemento precisamente pela página sem usar números escrotos

👉 Elemento apenas com as position handlers
![Elemento apenas com as position handlers](https://dev-to-uploads.s3.amazonaws.com/i/fv261v3sollp981p7ht1.png)

👉 Elemento com position e transform
![Elemento com position e transform](https://dev-to-uploads.s3.amazonaws.com/i/ezk19xls6p9kh8pglnxf.png)

Só de você conseguir movimentar o elemento de maneira cartesiana facilita 100% a sua vida. Agora, lembra que a posição é calculada à partir do **canto superior ESQUERDO**?

> Segunda convenção:
> NUNCA use `right` pra posicionar um elemento no eixo X 

### Bônus - `position: relative` e Grids;

Fato: elementos dentro de um grid são posicionados **dentro**do contexto do grid de maneira **cartesiana** (ou quase, mas tipo isso). Você só precisa definir uma `position` não estática para o elemento pai. Isso significa que dentro de um grid (50%, 50%) é o centro **exato**.

👉 Elemento pai com `display: grid` contendo 6 elementos filhos
![Exemplo de display grid contendo 6 elementos filhos](https://dev-to-uploads.s3.amazonaws.com/i/f0h4fsj4i9poc32cmnd4.png)

👉 Grid com um dos elementos filho posicionado com valores negativos, ficando fora do grid
![Grid com um dos elementos filho posicionado com valores negativos, ficando fora do grid](https://dev-to-uploads.s3.amazonaws.com/i/c6pdoqbpqxksm3bvxz7n.png)

👉 Grid com um dos elementos filho posicionado no centro da página apenas com _position handlers_
![Grid com um dos elementos filho posicionado no centro da página apenas com position handlers](https://dev-to-uploads.s3.amazonaws.com/i/xkskk8kaxpr56l6srz7y.png)

### E porque isso é útil?
Na maioria dos layouts, os componentes ficam dentro de um container que por sua vez fica dentro do body (ou é o body), como componentes grandes (sessões inteiras ou views) raramente mudam de posição, mas de orientação **ou** tamanho, você coloca eles em um grid.

![Exemplo de layout contendo header, nav, main, aside e div](https://dev-to-uploads.s3.amazonaws.com/i/lzr7ildjajm8zrskb2cg.png)

E se por um acaso você precisar mover qualquer um desses desgraçadinhos, você não só não vai quebrar o seu layout como vai fazer de forma cartesiana dentro do grid.

> Dica 💡: Com esse comportamento não funciona com flex, tenha isso em mente na hora de escolher como criar o seu layout. 

Agora, lembra que eu falei pra **nunca** usar a propriedade `right` com `position`? Dentro do grid pode. No caso de uso abaixo, se você colocar 0 em todas as propriedades de posicionamento, o elemento vai ocupar 100% do grid.

{% codepen https://codepen.io/camilo-micheletto/pen/xxVYqej %}

-----------

Se isso foi útil pra você, compartilha com quem você acha que isso vai ajudar. Dúvidas, sugestões? Comente ou manda um salve lá no meu Twitter [@lixeletto.](https://twitter.com/lixeletto).