# CSS element()

> Descubra a função CSS element() que renderiza qualquer parte de um site como imagem ao vivo. Crie efeitos avançados com reflexos e dobras 3D.

URL: https://dpw.dev/css/css-element/  
Publicado em: 2019-10-28  
Categoria: css  
Tags: interface, web-design  
Autor: Tárcio Zemel

O CSS Image Values and Replaced Content Module Level 4 [introduz a função `element()`](http://www.w3.org/TR/css4-images/#element-notation). Essa função foi definida anteriormente no nível 3 e, portanto, o Firefox já tem suporte para ela, desde a sua versão 4 (maio de 2011). Simplificando, **essa função renderiza qualquer parte de um site como uma imagem ao vivo (live image)!**

> Artigo baseado em [CSS element() function](http://iamvdo.me/en/blog/css-element-function).

Ao ver um elemento DOM renderizado diretamente no navegador, você obtém uma imagem dele. Todas as alterações nesse elemento serão vistas imediatamente, **em tempo real**, na imagem, incluindo a seleção de texto.

> **Atenção:** Na data de publicação deste artigo, somente Firefox consegue renderizar os exemplos que serão apresentados durante o artigo. Serão colocados vídeos para facilitar, mas, se quiser ver funcionando direto no navegador, teste as demos usando Firefox.

É uma feature muito poderosa, de sintaxe bem simples. Basta referenciar o elemento que se deseja obter uma visualização ao vivo usando seu atributo `id`. Por exemplo, aqui está um texto e uma imagem em `div#css-source`. A live image desse elemento pode ser usada como background de `div#css-result`.

```html
<div id="css-source">
  <p>Lorem ipsum</p>
  <img src="/images/blog/css-element/" alt="" />
</div>

<div id="css-result"></div>
```

```scss
#css-result {
  background: element(#css-source);
  background-size: 50% 50%;
}
```

À medida que `element()` cria uma imagem, é possível usar todas as propriedades CSS normalmente para controlá-la, como `background`, `background-repeat`, `background-size` etc.

Eis um demo funcional da coisa:

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

Lembre-se de que qualquer parte de um site pode ser referenciada, inclusive o site inteiro, se for preciso! Mas tenha cuidado: seu elemento pode ser filho da sua fonte (source), caso em que elementos podem aparecer 2 ou mais vezes. No entanto, o Firefox lida bem com referências recursivas.

`element()` pode facilmente elevar o design de CSS a outro nível, de maneira. Algumas poucas idéias que vêm à mente:

- Conteúdo duplicado em efeitos avançados
- Miniaturas em slides anterior/próximo
- Zoom em imagens de produtos em e-commerces
- background animado usando animações CSS ou referenciando video, canvas ou SVG
- Marca d'água com vários fundos da ideia de Lea Verou
- Enfim, o limite é a imaginação!

Algumas considerações a respeito:

- No momento, há prefixo para Firefox: -moz-element()
- Impacto no desempenho da renderização ao usar várias referências (não tão grave como filtros CSS, por exemplo, mas ainda algo que você deve considerar)
- [Há uma página de suporte do CanIUse](http://caniuse.com/#feat=css-element-function)
- [Issue com Chromium](https://code.google.com/p/chromium/issues/detail?id=108972)
- [Issue com WebKit](https://bugs.webkit.org/show_bug.cgi?id=44650)
- Nenhuma menção na [IE Platform Status](https://status.modern.ie/)

## Reflexo com CSS `element()`

Todos sabemos que reflexos não são mais uma tendência de web design -- olá, web 2.0! --, mas esse efeito é um bom ponto de partida para entender melhor o `element()`.

A demo é composta por uma imagem e sua `<figcaption>`, ambas dentro de uma tag `<figure>`. A função `element()` é usada no background do pseudo-elemento `::after` para obter uma visualização ao vivo de `<figure>` ao invertê-la ao longo do eixo Y e mascará-la usando uma máscara SVG.

Todo o efeito fica dentro de `[@supports](/css/css-supports-deteccao-nativa-suporte-css/)` para lidar com aprimoramentos para ficar consonante à filosofia de progressive enhancement:

```html
<figure class="reflection" id="css-element">
  <img src="/images/blog/css-element/image.webp" alt="" />
  <figcaption>San Francisco, CA</figcaption>
</figure>
```

```scss
@supports (background: element(#css-element)) {
  .reflection::after {
      background: element(#css-element);
      transform: scaleY(-1);
      mask: url('#mask');
      opacity: .3;
  }
}
```

A demo funciona no Firefox, com fallback para a propriedade antiga e não-padrão `-webkit-box-reflect` para navegadores baseados em WebKit (sem suporte no IE / Edge).

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="aOraoG" data-pen-title="Reflections with element()" data-user="iamvdo" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
      <span>See the Pen <a href="https://codepen.io/iamvdo/pen/aOraoG">
  Reflections with element()</a> by Vincent De Oliveira (<a href="https://codepen.io/iamvdo">@iamvdo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
      </p>
      <script async src="https://public.codepenassets.com/embed/index.js"></script>

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

Se já está cansado de ver esse efeito de reflexo, vamos a algo mais interessante.

## Efeito 3D de papel dobrado com `element()`

Em alguns efeitos avançados, às vezes é preciso lidar com conteúdo duplicado, e a única opção razoável aqui (até então) é o JavaScript. É muito fácil lidar com conteúdos estáticos (imagens, textos etc.), mas torna-se realmente complicado com os dinâmicos.

Com CSS `element()`, as coisas ficam muito mais simples.

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

Indo além, é possível aplicar o efeito de dobra 3D a qualquer coisa que esteja dentro da página, como um mapa interativo:

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

## Background animado com `element()`

Um efeito interessante também pode ser criar fundos animados. Bem, você pode pensar no antigo fundo animado em GIF, mas `element()` oferece novas possibilidades, como usar uma tag `<video>`, `<canvas>` ou `<svg>`.

Ao combinar , e conteúdo duplicado, torna-se possível criar esse efeito Muitcho LokoTM de dobra com mais de 30 peças, em que ainda é possível desenhar enquanto a animação acontece!

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

## `backdrop-filter` fake

Com o `element()`, torna-se bastante simples criar uma solução alternativa para `backdrop-filter` e, assim, aumentar o suporte de navegadores. O que é preciso fazer é definir o background de um elemento para ser a live view do elemento abaixo dele. Simples, certo?

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

Também possível com conteúdo dinâmico:

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

Também vale a pena mencionar que é possível `backdrop-filter` fake com filtros SVG. Algo como (veja a aba HTML):

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

## Como ocultar as referências

Em muitos efeitos, foi preciso criar uma máscara de camada para ocultar partes da página. Isso porque não é possível usar `display: none` em um elemento que está sendo usado como background. Na verdade, a live image não exibirá mais esse elemento.

Também é possível tentar agrupar o elemento de referência dentro de uma `<div>` com `height: 0` e `overflow: hidden`. Dessa forma, o elemento ainda está presente na página (e pode ser referenciado como uma visualização ao vivo), mas não está mais visível, portanto, não precisando mais de uma máscara de camada.

O problema é que alguns navegadores degradam o desempenho de elementos invisíveis (animações CSS, imagens GIF não animadas etc.) e não é isso que queremos nesse caso específico.

Então, parece que a técnica da máscara é realmente a melhor, por enquanto. Se você conseguir pensar em alguma outra solução, conta pra gente nos comentários.

## Conclusão

Apesar do seu (atual) baixo suporte a navegadores e desempenho de renderização duvidoso, deu para ver que CSS `element()` é incrível!

Se você conhecer outros exemplos tão legais quanto esses e/ou for criar demos usando `element()`, coloca nos comentários pra gente dar uma olhadinha e até complementar o artigo com esses novos exemplos.

---

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
