- Partindo da frosted acrylic UI de Forza Horizon 3 e Forza Motorsport 7, o texto organiza o processo de reproduzir na web um efeito semelhante de painel de vidro com HTML/CSS/JavaScript
- O centro do efeito é o Gaussian blur, e é preciso usar juntos o CSS
backdrop-filtere o-webkit-backdrop-filterdo iOS para reduzir diferenças entre navegadores - Como só o desfoque parece plano, usa-se
box-shadow: insetpara adicionar profundidade nas bordas e subsurface scattering, além de uma sombra normal para criar a sensação de que o painel flutua sobre o fundo - O reflexo da superfície é implementado com uma imagem de raios de luz em uma camada separada, imitando reflexos dinâmicos alinhados ao movimento do vidro com
background-attachment: fixedou JavaScript - A UI final combina as camadas
.glass,.lighte.drag-me, adicionando cantos arredondados, clipping e cor de fundo semitransparente para formar um componente de vidro reutilizável
Efeito de painel de vidro trazido da UI de jogos
- O objetivo é recriar em HTML o design frosted acrylic visto na experiência de desenvolvimento de UI de Forza Horizon 3 e Forza Motorsport 7
- O resultado é um painel de vidro arrastável, com desfoque de fundo, profundidade nas bordas, reflexo de luz, cantos arredondados e uma camada de cor semitransparente
- No começo, é apresentada uma receita final que pode ser copiada e usada imediatamente, e depois cada efeito é construído passo a passo
backdrop-filter para criar o desfoque de fundo
- O ponto central de um bom efeito de frosted glass é o Gaussian blur, que desfoca o fundo para fazê-lo parecer uma tela semitransparente
- Em CSS, isso é implementado aplicando
backdrop-filtercomblur - O elemento base de vidro começa com uma
divsimples e a classe.glassbackdrop-filter: blur(10px)-webkit-backdrop-filter: blur(10px)
- No iOS,
-webkit-backdrop-filteré necessário, a menos que se alterem configurações mais profundas - Como o suporte a
backdrop-filtersó chegou recentemente aos navegadores, usuários de Internet Explorer não conseguem ver a demo
Criando profundidade com bordas e sombras
- Aplicar apenas
backdrop-filter: blur(10px)pode fazer o vidro parecer plano e monótono - As bordas são implementadas com
box-shadow: insetem vez deborder: 1px solidborderafeta o tamanho do elemento e o posicionamento dos elementos filhos- Com
box-shadow: inset, os filhos podem preencher naturalmente a área de conteúdo do vidro sem ajustes como margem negativa
- Duas sombras inset brancas semitransparentes representam as bordas do vidro
- A primeira shadow representa a borda visível do lado de fora do vidro e, no exemplo, aparece nas bordas inferior e esquerda
- A segunda shadow representa a borda vista através do vidro e, no exemplo, aparece nas bordas superior e direita
- Como a luz diminui nas bordas vistas através do vidro, elas são configuradas de forma mais suave e transparente
- Adicionar um
box-shadowescuro normal pode dar a sensação de que o vidro está fisicamente flutuando sobre o fundo
Dispersão de luz e reflexo na superfície
- A sensação de luz se espalhando dentro do vidro é representada de forma simplificada usando
subsurface scattering - A implementação novamente usa
box-shadow: inset- Efeito curto de dispersão:
inset 0px 0px 10px 5px rgba(255, 255, 255, 0.025) - Efeito mais profundo de dispersão:
inset 0px 0px 40px 5px rgba(255, 255, 255, 0.025)
- Efeito curto de dispersão:
- Esse efeito aparece melhor ao arrastar o vidro sobre um fundo escuro
- Além da sensação de fundo desfocado e refratado, também se adiciona a característica de a luz refletir na superfície do vidro
- O reflexo de luz é implementado misturando uma imagem de raios de luz ao fundo
- Há um tutorial no YouTube e uma explicação em texto que podem servir de referência para criar uma imagem parecida
- Se a imagem for colocada diretamente como
background-imagedo elemento.glass, obackdrop-filtertambém a desfoca, por isso é usada uma camada separada como::before
Transformando reflexos estáticos em dinâmicos
- Se apenas a imagem de raios de luz for adicionada, o reflexo aparece, mas pode parecer preso à superfície do vidro mesmo quando ela se move
- A abordagem puramente em CSS adiciona
background-attachment: fixedao::before- A implementação é simples, mas pode não funcionar em todas as plataformas
- Para funcionar em todas as plataformas, usa-se JavaScript para imitar
background-attachment: fixed- Como lidar diretamente com
::beforeem JavaScript é ineficiente, usa-se um elementodiv.lightseparado - O elemento-alvo recebe o atributo
data-js-background-attachment-fixed
- Como lidar diretamente com
- A cada frame de animação, o JavaScript lê
getBoundingClientRect()do elemento-alvo e atualizabackground-positionna direção oposta à posição dentro da viewportbackgroundPositionX = -clientRect.xbackgroundPositionY = -clientRect.y
- O loop de repetição roda com
requestAnimationFrame
Estrutura final em HTML/CSS
- No HTML final da versão com JavaScript, a
.glasscontém a.lightpara reflexo da luz e a.drag-me, que é a camada de texto/cor
Drag Me
.glassé responsável pela forma básica do painel de vidro e pelos efeitos visuais- aplica desfoque de fundo com
backdrop-filtere-webkit-backdrop-filter - aplica bordas, sombras e efeito de dispersão com vários
box-shadow - usa
position: relativepara permitir que as camadas filhas preencham a área do elemento pai - aplica cantos arredondados com
border-radius: 5px - corta os elementos filhos para que não ultrapassem os cantos arredondados com
overflow: hidden
- aplica desfoque de fundo com
.lightusa a imagem de raios de luz como fundo repetidobackground-image: url(path/to/light.png)background-repeat: repeatbackground-size: 750pxopacity: 0.075- preenche todo o pai com
position: absolutee offsets0nos quatro lados - é renderizada atrás dos outros filhos com
z-index: -1
.drag-mecentraliza o conteúdo e cria uma camada de vidro colorida e semitransparentedisplay: flexalign-items: centerjustify-content: centerheight: 30pxbackground-color: rgba(12, 13, 14, 0.75)
Diferenças da versão sem JavaScript
- A versão sem JavaScript usa
.glass::beforeem vez de um elemento.lightseparado - A imagem de raios de luz é aplicada ao
::before, ebackground-attachment: fixedimplementa um reflexo preso à tela - Esse método não funciona em todas as plataformas, e a versão com JavaScript contorna isso atualizando
background-positiondiretamente
1 comentários
Comentários do Hacker News
Esteticamente eu gosto muito, mas há partes nas bordas que não fazem sentido fisicamente.
Do ponto de vista de um desenvolvedor embarcado, parece um tanto desperdiçador. Fico com a impressão de que todo cliente acaba calculando, toda vez, um filtro de blur “caro” para misturar com uma versão desfocada da imagem de fundo.
Talvez, por usar GPU e ser otimizado, no fim não tenha um custo tão grande, mas o desenvolvimento web hoje em dia, no geral, parece caminhar para ficar inchado demais. Até sites simples levam 5 segundos para carregar e empurram processamento pesado para o cliente — claro que isso não é culpa de quem escreveu este texto.
Cresci na época dos modems de 14,4k, então estou acostumado a pensar que largura de banda de rede é muito mais escassa e cara do que tempo de CPU.
Se dá para calcular facilmente no cliente, acho mais desperdiçador baixar uma imagem inteira pela internet. Para receber essa imagem, roteadores, servidores e até discos distantes precisam entrar em ação; usar tudo isso só para evitar um processamento sobre dados que já estão na RAM do cliente parece um desperdício maior.
Então ou entretenimento em si é desperdício, ou, se não for, também é aceitável gastar mais computação para tornar o entretenimento melhor.
Para redesenhar o que muda na UI, algum cálculo de GPU já é necessário de qualquer forma, e um blur simples pode ser adicionado de maneira bem eficiente. É provável que custe menos do que animar objetos DOM que não foram otimizados como camadas de GPU.
Considerando que hoje até os sites mais simples carregam mais de 1 MB de JavaScript e um monte de rastreadores que consomem CPU, um blur para efeito estético fica bem abaixo na lista de desperdícios.
Quando há muitas imagens em alta resolução, a largura de banda real da rede é finita e, especialmente em ambientes móveis com cobertura sem fio ruim, isso com certeza tem desempenho pior do que computação local. Hoje é surpreendente o que dá para fazer só com CSS/WebGL; antigamente, eram necessários muitos hacks e gambiarras para obter esse tipo de efeito.
Independentemente de o ato em si ser desperdício ou não, esse modo de pensar revela um problema maior da sociedade. Por que isso é necessário e por que enxergamos a ausência disso como algo ruim?
Dada a escala dos problemas sociais de hoje, quem realmente se importa se um painel de UI está desfocado ou não?
Ao tentar recriar o efeito Windows 7 Aero Glass no Android para ver o que dava para fazer com a nova API de shaders, extraí uma textura de “raios de luz” parecida.
O resultado acabou ficando muito parecido com o deste artigo, embora eu não tenha colocado sombra interna e tenha aumentado um pouco a saturação do fundo desfocado.
https://mastodon.social/@grishka/110524476584503201
Para ser sincero, a que foi feita para o tutorial nem é tão excelente assim. Gosto das linhas mais nítidas da versão do Windows 7.
Também pensei em ajustar a saturação e vi isso em outros exemplos, mas decidi não usar no texto. A imagem da lua que usei não tem muitas cores, então provavelmente não faria tanta diferença. Quem for criar seu próprio efeito de vidro deveria experimentar a saturação também.
O trabalho em si é excelente, e a forma de apresentar com uma demo interativa também é boa. É divertido arrastar a janela sobre a lua.
Mas não gosto do uso do efeito de vidro fosco em design de interface, e senti que foi um retrocesso quando ele foi adicionado ao Mac OS. Designers se encantam fácil demais com esse efeito, mas na prática ele nunca é ideal. Especialmente quando o conteúdo atrás do painel é dinâmico ou criado pelo usuário.
É como o metal escovado dos anos 2010, e é surpreendente que tenha vazado do Windows Vista e se espalhado por toda parte.
Claro que o design também afeta a função, mas o objetivo principal é tornar a experiência do usuário mais agradável.
Acho que o esqueumorfismo torna as interfaces mais agradáveis do que a tendência minimalista de achatar tudo que prevaleceu por mais de uma década. Ornamentos visuais que imitam superfícies e materiais do mundo real acrescentam familiaridade e acessibilidade. Em termos práticos, o design flat dificulta distinguir elementos e estados, enquanto, na época dos botões 3D, do metal escovado e do vidro fosco, tudo era muito mais claro.
Acho que agora o pêndulo está voltando. Como mais designers estão evitando a aparência plana, espero que uma UI mais amigável para humanos volte a surgir.
Blur geralmente não é a resposta certa, mas às vezes é a escolha correta.
Em 2008, antes de o CSS dar suporte a
backdrop-blur, já fiz um experimento em CSS para obter um efeito parecido: https://webdev.andersriggelsen.dk/aero/A abordagem era aplicar um efeito de vidro a uma imagem de fundo em posição fixa, previamente desfocada: https://webdev.andersriggelsen.dk/aero/bgl.jpg
O desempenho é muito melhor do que um desfoque gaussiano em tempo real, mas a desvantagem de não permitir imagens de fundo dinâmicas continua a mesma
Dava para criar o efeito de vidro mesmo dentro de um frame que podia se mover dinamicamente. Não me lembro se usei iframe, então teria de procurar o código, mas, considerando a época, provavelmente usei
Estou no Windows 10 19045.5131, e o Chrome é a versão mais recente, Version 131.0.6778.86 (Official Build) (64-bit)
A realização técnica é legal, mas vejo isso como UX ruim
O conteúdo dentro de painéis translúcidos é mais difícil de ler ou entender do que sobre um fundo sólido consistente, e o contraste com o fundo é baixo e irregular. Além disso, se algo se move por baixo, pode distrair e desorientar
Uma boa integração deve ajustar a intensidade do efeito para não deixar a UI exagerada, verificar o suporte ao recurso para evitar decoração extra quando o desfoque não for suportado, e verificar os recursos de tela e vídeo para não renderizar em dispositivos em que talvez não haja GPU suficiente
Também deve verificar as preferências do usuário para oferecer uma cor sólida de alto contraste a usuários que têm dificuldade com fundos complexos, limitar o alcance do efeito e das sombras conforme o espaço disponível, e ajustar o desfoque e a opacidade levando em conta a complexidade e o contraste do fundo sob a área desfocada
Também é necessário garantir que o desfoque e as sombras escalem de forma adaptativa de acordo com a tipografia. UX é, em essência, o design de como o usuário vivencia a interação com o app inteiro, não algo que dá certo ou errado por causa de uma única escolha de estilo
Isso garantia a legibilidade do texto mesmo em casos extremos em que o fundo era preto. Em CSS, dá para reproduzir isso com a propriedade
text-shadowMas em jogos há mais lugares onde ele pode ser usado. Em especial, pode ser adequado em um HUD, quando você não quer esconder o fundo, que é a área principal com a qual o usuário interage
Bom contraste é um desafio em qualquer elemento de design, seja com cor sólida ou efeito de vidro
A ideia de que o que acontece no fundo distrai e desorienta também é muito subjetiva. Assim como se pode reduzir a opacidade de uma cor sólida, também se pode reduzir a translucidez do vidro
Essa crítica é difícil de considerar objetivamente verdadeira, e há maneiras de integrar esse elemento de design evitando esses problemas. A captura de tela do Forza parece boa e, quando vi na prática, o fundo também não distraía. Em vez disso, você ganha uma UI mais interessante e visualmente agradável do que um fundo sólido. Isso pode ser mais importante em videogames, mas também pode ser usado com elegância em design de OS e web
Se você precisa de muito contexto, o desfoque não é uma boa escolha; se não precisa de contexto nenhum, também não é uma boa escolha
Mas, às vezes, ele é uma excelente escolha
O exemplo interativo é bom, mas teria sido ainda melhor se houvesse um toggle para comparar lado a lado com a etapa anterior ou alternar entre elas
Na maioria das etapas, a melhoria era sutil demais para perceber a diferença
Há uns 10 efeitos sobrepostos, e, a menos que o objetivo seja atingir a estética mais exigente possível, uns 7 deles são exagero
Bastaria usar cor de fundo, desfoque e talvez sombra ou borda
Já na terceira etapa, só com desfoque e sombra, sai um pedaço de vidro bem decente. Pessoalmente, eu recomendaria misturar a isso uma imagem estática de raios de luz. Acho que a maioria das aplicações não precisa do efeito completo em JavaScript. É divertido, mas pode distrair
Só com desfoque, sombra e raios de luz, já dá para chegar bem perto da imagem do Forza lá de cima
Acho que esse foi um dos motivos pelos quais todo mundo foi para o flat design. O Windows Vista e o efeito de vidro eram bonitos, mas tinham um custo computacional alto
O flat design é esteticamente controverso e, especialmente para usuários mais velhos, pode ser mais difícil de usar do que o design esqueumórfico [0][1]
Se o realismo pode ajudar na usabilidade, acho perfeitamente razoável usar efeitos como esse na web
[0]: https://www.tandfonline.com/doi/abs/10.1080/0144929X.2020.18...
[1]: https://www.sciencedirect.com/science/article/abs/pii/S01419...
n <= 3Não sei se é uma questão de acessibilidade, desempenho, manutenção ou outro motivo
Entre minhas habilidades de desenvolvimento, CSS é de longe a mais fraca, então estou totalmente sem noção sobre boas e más práticas
É interessante porque parece que demos uma volta completa
Uma das primeiras demos de CSS, uma demo para CSS 1, era um efeito de vidro fosco: https://meyerweb.com/eric/css/edge/complexspiral/glassy.html
Sinceramente, é bem impressionante. É sempre um prazer ver o quanto CSS pode ser criativo e poderoso
Mas sinto que há um nível em HTML/CSS que nunca vou entender. Esta demo é exatamente isso: essa pessoa está criando uma janela fosca, enquanto eu ainda não consigo centralizar uma única
divdivmuitas vezes é uma boa ideiaSe você olhar para a maioria dos sites modernos, vai ver
divs empilhadas como uma pilha enorme. Se quiser umadivcentralizada, fica relativamente fácil criar dentro dela mais umadivque ocupe todo o espaço a ser centralizadoMuitos truques visuais são parecidos, mas este exemplo é muito limpo, o que o torna ainda mais impressionante
Não é exatamente vidro fosco, mas experimentei colocar um efeito de vidro na barra lateral de https://www.gyan.dev/ffmpeg/builds/