# Técnicas CSS para elementos de cobertura

> Técnicas CSS essenciais para elementos de cobertura (overlay). Aprenda a sobrepor elementos com position, z-index, classes utilitárias e melhores práticas!

URL: https://dpw.dev/css/elementos-cobertura-css/  
Publicado em: 2021-01-22  
Categoria: css  
Autor: Tárcio Zemel

Em muitos projetos, é preciso usar o CSS para fazer **elementos de cobertura** (cobrir um elemento com outro). Veja algumas técnicas possível para alcançar este efeito através de utilitários CSS.

![Quadrado listrado representando um elemento de cobertura CSS (seu código será mostrado mais à frente). ](/images/blog/elementos-cobertura-css/image.webp)

Aqui está algo que é bastante comum de se fazer repetidamente em CSS: "cobrir" completamente um elemento com outro -- daí o nome **elemento de cobertura**. :)

É sempre o mesmo CSS: o primeiro elemento (aquele que precisa ser coberto) tem `position: relative` aplicada a ele; o segundo, `position: absolute` e é posicionado de forma que todos os quatro lados se alinhem às bordas do primeiro elemento.

O CSS completo se parece com:

```scss
.original-element {
  position: relative;
}

.covering-element {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
```

Freqüentemente, é um título (_title_) ou legenda (_caption_) que precisa cobrir uma imagem; às vezes, com uma cor de fundo translúcida ou gradiente -- isso também é chamado de sobreposição. Normalmente, é um filho direto do primeiro elemento que está sendo sobreposto, mas nem sempre.

Às vezes, é necessário sobrepor um pseudo-elemento, talvez até fazer a transição ou animá-lo para um estado de foco. De qualquer maneira, isso é feito com tanta frequência, que é totalmente legítimo criar uma classe de utilitário para ajudar, em vez de escrever as propriedades CSS à mão todas as vezes.

## Classes de utilidade (ou utilitárias) para elementos de cobertura

Já citamos algumas vezes classes utilitário aqui no dpw -- por exemplo, em [nossa live sobre Namespaces CSS](https://www.youtube.com/watch?v=24inN5LDO3M). Tratam-se classes que devem ter um e somente um propósito e que podem ser aplicadas em diversos elementos.

Por exemplo, é possível ter uma classe de alinhamento centralizado de texto:

```scss
.text-center {
  text-aling: center;
}
```

Então, sempre que for necessário que um elemento tenha texto centralizado, ao invés de colocar a propriedade e o valor, utiliza-se essa classe -- ou, caso a stack do projeto conte com pré-processador de CSS, ela é estendida.

É possível usar classes de utilitários de diversas maneiras, desde as mais insanas (como é feito no Tailwind), até as mais normais, com parcimônia e na medida em que o projeto as demanda.

E uma _utilty class_ não precisa, necessariamente, se ater a somente uma propriedade CSS. Pensando em uma classe de utilitário para elemento sobreposto, esta incluiria várias propriedades.

Por exemplo, um utilitário desta natureza poderia ser algo como:

```scss
.overlay {
  position: absolute;
  content: '';
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
```

Embora seja muito flexível como um utilitário, usar `position: absolute` define a posição do elemento em relação ao ancestral de posição relativa mais próximo, então é preciso lembrar de definir `position: relative` ao elemento que se quer cobrir (e garantir que seja um ancestral do elemento de cobertura).

Na maioria dos casos, o elemento que se usa como uma sobreposição é um filho direto ou um pseudo-elemento, portanto, pode fazer sentido criar mais utilitários para aplicar nesses casos, o que significa que não é preciso definir `position: relative`.

Qualquer uma dessas 3 classes pode, ao invés disso, ser aplicada ao elemento-pai (ou seja, o elemento original que é preciso cobrir):

```scss
.overlay-child,
.overlay-before,
.overlay-after {
  position: relative;
}

.overlay-child > *,
.overlay-before::before,
.overlay-after::after {
  position: absolute;
  content: '';
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
```

Agora existem 3 utilitários para se aplicar adicionalmente quando é necessário direcionar o elemento que está fazendo a cobertura:

- `overlay-child` (para posicionar um elemento-filho direto)
- `overlay-before` (para posicionar um pseudo-elemento `::before`)
- `overlay-after` (para posicionar um pseudo-elemento `::after`)

Um exemplo de quando é possível usar a sobreposição em vez de uma das classes de segmentação de pais é se o elemento de cobertura não for um filho direto, mas um descendente mais abaixo na árvore DOM.

[Exemplo no CodePen](https://codepen.io/anon/pen/KKgzJQy)

## Dica bônus: pegar o elemento-pai mais próximo com JavaScript

Já que estamos no assunto de diferentes **técnicas CSS para elementos de cobertura**, quando é preciso lidar com componentes complexos e posicionamento absoluto, um `position: relative` maroto às vezes pode ser a causa de bugs de layout.

Para debugar, geralmente é necessário encontrar o ancestral em posição relativa mais próximo do elemento em posição absoluta que está causando problemas. Felizmente, é possível usar um pouquinho de JavaScript para ajudar.

Nas DevTools do Chrome e Firefox, digitar `$0` no console retornará o elemento atualmente selecionado. Se usar `$0.offsetParent`, o ancestral posicionado mais próximo do elemento atualmente selecionado será retornado.

Então, é possível verificar se ele tem `position: relative` pelo painel Styles -- ou através de JavaScript, com `getComputedStyle($0.offsetParent).position`.

## CSS Logical Properties

Posicionar um elemento dessa maneira está prestes a se tornar mais conciso com a ajuda da nova propriedade CSS `inset`. Parte da especificação [CSS Logical Properties](https://www.w3.org/TR/css-logical-1/#inset-properties), `inset` é efetivamente uma abreviação para as propriedades de posicionamento `top`, `right`, `bottom`, `left`.

Também há novas propriedades lógicas, que permitem alcançar algo parecido: `inset-block-start`, `inset-block-end`, `inset-inline-start` e `inset-inline-end`. Para o modo de escrita ([writing mode](https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode)) padrão da esquerda para a direita (_left-to-right_), isso será mapeado para `top`, `bottom`, `left`, `right`, nessa ordem.

Mas outros modos de escrita (bem como a propriedade `direction`) farão com que os valores sejam mapeados de forma diferente. No momento, porém, é preciso apenas da propriedade `inset` para o utilitário do elemento de cobertura.

Voltando ao código, ele poderia ser refatorado de:

```scss
.overlay {
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
}
```

Para:

```scss
.overlay {
  inset: 0;
}
```

Fazendo do código menor e igualmente eficiente:

```scss
.overlay-child,
.overlay-before,
.overlay-after {
  position: relative;
}

.overlay-child > *,
.overlay-before::before,
.overlay-after::after {
  position: absolute;
  content: '';
  inset: 0;
}
```

### Suporte cross-browser

No momento da publicação deste artigo, [`inset` já tem um suporte cross-browser (moderno) bastante amplo](https://caniuse.com/?search=logical%20properties), portanto, você já pode começar a pensar em usar a nova propriedade CSS em produção -- dependendo do caso, forneça um fallback para navegadores sem suporte.

## Método alternativo para elementos de cobertura: CSS Grid

Algo interessante é que não necessariamente é preciso usar posicionamento absoluto: o utilitário CSS para cobertura de elementos também pode ser feito ao usar CSS Grid para cobrir um elemento com outro!

O código (mais enxuto, inclusive) é parecido com:

```scss
.element {
  display: grid;
}

.overlay {
  grid-area: 1 / 1 / -1 / -1;
}
```

Se a sobreposição for o único elemento filho, não é preciso nem definir a grid area, mas nada impede prevenir para o caso de ser preciso adicionar outros elementos-filho -- caso contrário, seria arriscado acontecer algum efeito colateral quando os itens são colocados automaticamente na grid.

```scss
.overlay-child,
.overlay-before,
.overlay-after {
  display: grid;
}

.overlay,
.overlay-child > *,
.overlay-before::before,
.overlay-after::after {
  content: '';
  grid-area: 1 / 1 / -1 / -1;
}
```

Eis um demo com a técnica usando CSS Grid:

[Exemplo no CodePen](https://codepen.io/anon/pen/NWRrgxX)

## Conclusão

Usar utilitário CSS é uma técnica já conhecida. Existem maneiras de otimizar seu entendimento e eficiência, mas sua intenção de uso fica bem clara.

Quando se deparar com casos de CSS em que seja necessário repetir muitas vezes as mesmas propriedades, é interessante ponderar a respeito do uso de utilitários CSS.

Um dos casos, abordados no artigo, é sobre criar utilitários que tratam **elementos de cobertura usando diferentes técnicas**. A depender do projeto, pode ser uma bela adição às folhas de estilo.

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
