5 pontos por GN⁺ 2025-09-09 | 2 comentários | Compartilhar no WhatsApp
  • Apresenta como recriar na web o efeito Liquid Glass revelado pela Apple na WWDC de 2025 usando CSS, SVG e cálculos de refração baseados em física
  • Explica o princípio da refração e o processo de simulação da refração e de representação da superfície de vidro com a lei de Snell
  • Mostra como gerar um campo vetorial de deslocamento adequado para renderização com SVG displacement map e demonstra que ele pode ser aplicado a componentes reais de UI
  • No Chrome, é possível usar SVG filter como backdrop-filter, e o texto apresenta exemplos de aplicação em vários elementos de UI (lupa, switch, player etc.)
  • Menciona que o efeito pode ser implementado em tempo real, mas há problemas de compatibilidade entre navegadores e limitações de desempenho, além de citar planos futuros de open source

Introdução

A Apple apresentou pela primeira vez o efeito Liquid Glass na WWDC de junho de 2025. Esse efeito faz com que elementos da interface pareçam vidro refrativo curvo, oferecendo uma experiência visual semelhante à de uma superfície de vidro real. Este texto aborda um exercício prático para criar um efeito parecido na web com CSS, SVG displacement map e cálculos de refração baseados em física. O objetivo não é uma implementação completa, mas uma prova de conceito escalável que reproduz características principais como refração e destaques especulares. A construção do efeito começa pelos princípios básicos de como a luz sofre refração ao atravessar materiais diferentes e avança passo a passo. A demo interativa fornecida no final atualmente funciona corretamente apenas no Chrome.

Entendendo o fenômeno da refração

Refração é o fenômeno em que a luz muda de direção ao passar de um material para outro. Isso acontece porque a velocidade da luz varia conforme o material, e a relação entre ângulo de incidência e ângulo de refração pode ser expressa pela lei de Snell:

  • n1 * sin(θ1) = n2 * sin(θ2)
    • n1: índice de refração do primeiro meio
    • θ1: ângulo de incidência
    • n2: índice de refração do segundo meio
    • θ2: ângulo de refração

O que pode ser observado no diagrama interativo:

  • Se os dois meios tiverem o mesmo índice de refração, a luz segue em linha reta sem refratar
  • Quando o segundo meio tem índice de refração maior, a luz refrata em direção à normal
  • Se o segundo meio tiver índice de refração menor, a luz se afasta da normal e, em alguns casos, pode ocorrer reflexão interna total
  • Se a luz incidente for perpendicular à superfície, ela segue reta independentemente do índice de refração

Limites deste projeto

Para limitar a complexidade e simplificar o algoritmo, foram definidas as seguintes condições:

  • O índice de refração do meio externo é 1 (ar)
  • O material interno de vidro usa 1.5 (vidro comum)
  • Apenas um evento de refração é considerado (ignorando a refração na saída)
  • A luz incidente é sempre perpendicular ao plano de fundo
  • Todos os objetos são formas 2D e apenas circulares (é possível expandir para retângulos etc., mas isso exige cálculos)
  • Não há espaço entre o objeto e o plano de fundo
  • Nessas condições, é possível calcular todos os raios de forma simples com a lei de Snell

Criando a superfície de vidro

Para implementar o efeito Liquid Glass, é preciso definir a seção transversal do vidro virtual (lente ou painel curvo) com uma função matemática.

Função de superfície

A superfície do vidro é definida por uma surface function, que representa a espessura desde a borda até a parte interna plana

  • Valor de entrada 0: contorno externo, 1: fim do bezel (início da área plana)
  • A partir da derivada da espessura em cada ponto, obtém-se o vetor normal da superfície
const height = f(distanceFromSide);
const delta = 0.001;
const y1 = f(distanceFromSide - delta);
const y2 = f(distanceFromSide + delta);
const derivative = (y2 - y1) / (2 * delta);
const normal = { x: -derivative, y: 1 };

Principais tipos de função de superfície

  • Convex Circle: y = sqrt((1 - (1 - x))^2)
    • Forma simples de arco circular; fica plana rapidamente em direção ao interior, deixando a refração da borda mais evidente
  • Convex Squircle: y = ((1 - (1 - x))^4)^(1/4)
    • Forma muito usada pela Apple; a transição entre curva e plano é suave, e o efeito continua natural mesmo ao ampliar
  • Concave: y = 1 - Convex(x)
    • Forma côncava (oposta da convexa), em que a luz refrata para fora do limite do objeto, exigindo amostragem externa
  • Lip: y = mix(Convex(x), Concave(x), Smootherstep(x))
    • Estrutura composta com uma borda saliente e uma curvatura rasa no centro

Só essas quatro funções já permitem comparar com eficiência as diferenças de refração conforme o formato da superfície.

Simulação

De acordo com cada função de superfície, é simulada a trajetória de refração dos raios, visualizando a diferença real do efeito.

  • O formato convexo (Convex) concentra o caminho da luz para dentro, enquanto o côncavo (Concave) empurra para fora
  • O Liquid Glass da Apple prefere majoritariamente formas convexas (com exceções como o Switch)
  • As setas do fundo são coloridas pela magnitude para indicar a quantidade de refração (deslocamento)
  • Distâncias iguais em relação às bordas esquerda e direita produzem o mesmo deslocamento, permitindo reutilização eficiente

Geração do campo vetorial de deslocamento

É construído um campo vetorial que representa, em cada posição da superfície de vidro, a direção e a intensidade do deslocamento da luz

  • Em uma forma circular, o movimento ocorre sempre na direção da normal em relação à borda

Pré-cálculo da magnitude do deslocamento

  • Como a magnitude do deslocamento é simétrica para cada distância em relação à borda, os valores são pré-calculados por unidade de raio e armazenados em um array
  • Em 2D, o cálculo é feito apenas uma vez (simulando 127 raios) e depois rotacionado em torno do eixo z para gerar o campo completo

Normalização dos vetores

Para usar os vetores no displacement map, é feita a normalização (escala máxima 1.0)

  • Os demais vetores têm sua magnitude dividida pelo valor máximo de deslocamento
const maximumDisplacement = Math.max(...displacementMagnitudes);
displacementVector_normalized = {
  angle: normalAtBorder,
  magnitude: magnitude / maximumDisplacement,
};

No SVG displacement map, ao converter novamente para pixels reais, o valor máximo original é restaurado multiplicando-se pela escala.

SVG Displacement Map

Para aplicar na prática os resultados matemáticos do cálculo de refração ao rendering no navegador, é usado um SVG displacement map

  • Cada canal (RGBA, 8 bits) de <feDisplacementMap /> pode ser responsável pelos eixos X e Y do deslocamento
  • Cada canal tem valores de 0 a 255, e 128 significa neutro (sem deslocamento)
  • O displacement map precisa obrigatoriamente ser convertido em imagem
<svg colorInterpolationFilters="sRGB">
  <filter id={id}>
    <feImage
      href={displacementMapDataUrl}
      x={0}
      y={0}
      width={width}
      height={height}
      result="displacement_map"
    />
    <feDisplacementMap
      in="SourceGraphic"
      in2="displacement_map"
      scale={scale}
      xChannelSelector="R"
      yChannelSelector="G"
    />
  </filter>
</svg>

Scale

Os valores dos canais Red(X) e Green(Y) são mapeados para o intervalo [−1, 1]

  • O atributo scale multiplica pelo deslocamento máximo em pixels para realizar o rendering real
  • Também é possível animar scale para ajustar a intensidade do efeito

Conversão de vetor → valores Red/Green

  • O vetor de deslocamento (ângulo, magnitude) é convertido em coordenadas cartesianas x e y e então mapeado para 0~255 com base em 128 (neutro)
const x = Math.cos(angle) * magnitude;
const y = Math.sin(angle) * magnitude;
const result = {
  r: 128 + x * 127,
  g: 128 + y * 127,
  b: 128,
  a: 255,
};

A imagem finalizada pode então ser usada como displacement map em um filtro SVG.

Playground

No Playground interativo, é possível alterar em tempo real o formato da superfície, a espessura do bezel, a espessura do vidro e a escala do efeito, observando as mudanças no campo de refração, no displacement map e no rendering final.

Specular Highlight

Por fim, adiciona-se o specular highlight (destaque brilhante nas bordas da superfície de vidro)

  • A implementação da Apple usa um tipo de rim light, no qual a intensidade do brilho varia conforme a normal da superfície e o ângulo da fonte de luz

Combinando refração e Specular Highlight

No filtro SVG final, o displacement map e a imagem de specular highlight são carregados separadamente com <feImage /> e combinados com <feBlend /> para criar o efeito final

  • Ajustando os parâmetros do filtro, é possível produzir vários visuais diferentes

Usando SVG filter como backdrop-filter

  • Para aplicar de fato o efeito Liquid Glass a componentes de UI, é necessário o suporte do Chrome a backdrop-filter: url(#...)
  • Como o tamanho da imagem do backdrop-filter não é ajustado automaticamente, é essencial preparar um displacement map compatível com o tamanho do elemento
.glass-panel {
  backdrop-filter: url(#liquidGlassFilterId);
}

Aplicação em componentes reais de UI

Com base na refração calculada e no displacement map, são implementados exemplos aplicados a componentes de UI com aparência realista

  • Apenas o Chrome consegue tratar SVG filter como backdrop-filter
  • Os exemplos não são componentes reais de produção, mas demonstrações de como o efeito Liquid Glass pode ser aplicado a diferentes interfaces

Magnifying Glass

  • Usa refração e zoom em ambos os lados, com dois displacement maps
  • Sombras e ajuste de escala acrescentam um efeito interativo
  • É possível deformar a lente por arraste e observar a trajetória da refração
  • Inclui um specular highlight suave

Searchbox

  • Aplica o efeito Liquid Glass a uma caixa de entrada padrão

Switch

  • Usa um bezel do tipo lip, com exterior convexo e interior côncavo
  • Apenas o slider central fica ampliado/reduzido, enquanto as bordas refratam a imagem interna

Slider

  • Usa um bezel convexo, exibindo o valor atual normalmente através do vidro, enquanto os dois lados aplicam refração ao fundo

Music Player

  • Imita o estilo de painel Liquid Glass do Apple Music

  • Usa bezel convexo e specular highlight sutil para dar sensação de volume

  • Carrega capa do álbum e informações como nome da faixa usando a iTunes Search API

  • (fornece uma lista com nomes de faixas e informações do álbum)

Conclusão

Este protótipo representa de forma simplificada o conceito de Liquid Glass da Apple com efeitos de refração em tempo real e highlights simples. Na prática, ele só funciona de verdade em navegadores baseados em Chromium (ou Electron), e em outros navegadores pode ser substituído por uma camada de blur.
Trata-se de uma implementação experimental, e regenerar o displacement map a cada mudança de forma/tamanho é muito ineficiente (apenas alguns parâmetros, como o scale do filtro, podem ser animados).
Há a possibilidade de publicação futura em open source, e o autor afirma ter interesse em otimização e organização do código.

2 comentários

 
bobross0 2025-09-16

Parece ser o mais parecido com o Liquid Glass que vi na web.

 
GN⁺ 2025-09-09
Comentários do Hacker News
  • Já tive experiência criando algo parecido com shaders em WebGL; a vantagem é funcionar em vários navegadores; compartilhei https://real-glass.vercel.app; a parte difícil foi reproduzir corretamente o efeito de refração atrás de elementos HTML reais
    • Fiquei curioso sobre o que causa o efeito de fantasma/atraso quando o efeito de vidro é colocado sobre texto e movido
    • Acho incrível; parece até que foi implementado o efeito de dispersão com separação de cores nas bordas
    • O visual é ótimo, mas está lento demais para uso real; o do autor original roda muito mais suave
    • Impressionante
  • É impressionante que haja engasgos até em um Macbook Pro M4-Max sempre que se rola a página; se esse tipo de tecnologia fosse aplicado à UI inteira, minha principal preocupação seria desempenho; provavelmente a Apple consegue isso porque fez uma otimização extrema
    • Como autor do texto, tentei corrigir os problemas de desempenho antes, mas alguém acabou postando no HN antes do que eu esperava; a observação está correta, no momento está um pouco lento e precisa de mais otimização; não só a refração/mapa de deslocamento, mas outras partes como as visualizações ainda não foram otimizadas
    • Como avancei rapidamente nas melhorias de desempenho no Chrome, provavelmente já ficou um pouco melhor; no Safari, a renderização SVG ainda é lenta; como foi publicado inesperadamente, ainda restam pontos a melhorar
    • Neste site, a rolagem não é suave; na maioria dos casos, CSS não consegue aproveitar bem a GPU; parece que a Apple adicionou tratamento especial no silício para lidar com a UI
    • Aconteceu a mesma coisa no meu computador; o efeito de borda também não apareceu corretamente
  • O conteúdo é bom, mas a composição e a qualidade do artigo como um todo também foram excelentes; o conceito de liquid glass em si não traz vantagens adicionais muito concretas para a UX (e, se usado em excesso, pode até prejudicá-la), mas é uma experiência nova e divertida
  • O autor enfatiza que é uma demo exclusiva para Chrome e escreveu que a demo interativa final só funciona no Chrome (por causa das limitações do backdrop-filter com filtro SVG), embora seja possível ler o artigo e ver simulações simples em outros navegadores. Em resposta, houve o comentário humorístico: "Desonra para toda a sua família!"
    • Permitir esse tipo de coisa é inevitável; o objetivo é justamente mostrar algo que só é suportado em navegadores específicos
    • Curiosamente, no meu caso a página ficou mais lenta e a rolagem mais travada no Chrome, enquanto no Firefox, apesar de o efeito não ser suportado, ficou até mais suave; ainda assim, fiquei muito impressionado com o artigo em si
    • Tive uma reação parecida, mas curiosamente no Firefox também pareceu funcionar bem
    • Se você quer a referência, pode consultar: https://youtu.be/GamP4chXJ2I?t=17
  • Era esperado que a linguagem de design liquid glass chegasse à web, mas se um site for drenar minha bateria por causa da distorção de texto, não pretendo ficar muito tempo; como muita gente já apontou os engasgos, não vou repetir isso
  • É um trabalho bonito e claramente feito com muito capricho, mas liquid glass significa a linguagem de design como um todo: elementos próximos se fundindo como metaballs, vários modos de tingimento/transparência, controles em uma camada separada do conteúdo etc.; esta implementação, por assim dizer, está mais para um simples "glass shader"
    • A fusão de elementos pode ser resolvida com um filtro bem mais simples, o filtro "Goo"; é uma técnica usada há muito tempo; implementação de referência: https://codepen.io/lenymo/pen/pJzWVy
  • Fiz um fork da biblioteca JS para liquid-glass e adicionei um patch de correção de posicionamento; é divertido de usar em apresentações; código-fonte: https://github.com/nkzw-tech/liquid-glass
    • Legal, na verdade gostei mais deste aqui
  • No Firefox só parte dos efeitos funciona (mas em compensação o desempenho fica garantido!), e ainda assim é a melhor implementação que já vi; isso impressiona ainda mais porque pesquisei bastante sobre o tema nos últimos dias; o que mais gostei foi o design do site e as visualizações interativas feitas com tanto cuidado; senti que está no mesmo nível dos trabalhos de Bartosz Ciechanowski e Josh Comeau; espero que o código-fonte seja aberto
  • Acho uma ótima tentativa apesar das limitações de suporte entre navegadores; os exemplos interativos inline agregaram valor extra; em certo momento, parecia que eu estava lendo um artigo do Ciechanowski (referência: https://ciechanow.ski/)
  • Fico curioso se a nova barra de rolagem e os botões com ray tracing realmente são mais funcionais e aumentam a produtividade em relação aos antigos botões do Turbo Vision em modo texto ou do Windows 3