efeito pixelização sem javascript (gsap)
efeito interessante pra usar de entrada, ou como interação do usuário, com as novas propriedades :has() e anchor-position torna possível.
Esse efeito revela uma imagem "pixel por pixel": em vez de mexer na imagem em si, você cobre ela com uma grade de divs sólidas e some com cada uma via animação de opacidade, criando a sensação de montagem progressiva. Dá pra usar como animação de entrada (as divs somem sozinhas ao carregar a página) ou adaptar pra disparar só no hover. Tudo isso só com @keyframes/transition, CSS nesting nativo e Anchor Positioning — zero GSAP, zero dependência externa, zero JS calculando posição de mouse.
section { display: flex; flex-wrap: wrap; width: 600px; height: 600px; background: url('sua-imagem.jpg') no-repeat; background-size: contain; &:has(div:hover) { &:after { opacity: 1; } } div { background: #eee; width: 60px; height: 60px; animation: pixelated 1s forwards; animation-delay: calc(var(--si) * .1s); &:hover { anchor-name: --div; } } &:after { content: ''; position: absolute; position-anchor: --div; width: anchor-size(width); height: anchor-size(height); left: anchor(left); top: anchor(top); background: #fff; opacity: 0; pointer-events: none; } } @keyframes pixelated { to { opacity: 0; } }
A entrada acontece porque animation: pixelated dispara sozinha assim que a div existe no DOM — o animation-delay variável via --si é o que quebra a uniformidade e dá aquele ar orgânico, em vez de uma cortina reta abrindo. Pra virar hover em vez de entrada, é só trocar o gatilho: tira o animation fixo do div e usa transition com section:hover div { opacity: 0; } — transition anima suave nos dois sentidos (entrando e saindo do hover), enquanto animation com forwards só cobre a ida e, ao perder o hover, simplesmente some sem reverter suave. Já o :after com anchor-name/anchor() é um bônus separado no código: destaca com um quadrado branco o pixel exato embaixo do cursor, sem nenhum cálculo de posição em JS.
const section = document.querySelector('section'); for (let i = 0; i < 100; i++) { const pixel = document.createElement('div'); pixel.style.setProperty('--si', Math.floor(Math.random() * 5) + 1); section.appendChild(pixel); }
O JS existe só pra gerar as 100 divs (grade 10x10 pra fechar os 600x600px da section) e sortear o --si de cada uma — é a parte "programática" do efeito, que poupa de digitar cada delay na mão.
E é exatamente aí que entra a versão sem JS: dá pra escrever as 100 divs direto no HTML e fixar --si (ou até animation-delay) via style inline em cada uma, tipo <div style="--si:3"></div>. Perde só a aleatoriedade automática (a menos que você sorteie os valores você mesmo antes de colar), mas funciona idêntico, sem uma linha de JS. Suporte pra anchor()/anchor-size() hoje já é bom nos três motores principais (Chrome, Firefox e Safari), mas por ser relativamente recente vale um check no Can I Use antes de produção — o efeito de pixelização em si (@keyframes/transition + delay) já roda liso em qualquer navegador moderno.