- Parte de la UI de acrílico esmerilado de Forza Horizon 3 y Forza Motorsport 7, y resume el proceso para recrear en la web un efecto similar de panel de vidrio con HTML/CSS/JavaScript
- El centro del efecto es el desenfoque gaussiano, y para reducir diferencias entre navegadores hay que usar
backdrop-filterjunto con-webkit-backdrop-filterpara iOS - Como solo aplicar desenfoque puede verse plano, se agrega profundidad en los bordes y subsurface scattering con
box-shadow: inset, y una sombra normal crea la sensación de que flota sobre el fondo - Los reflejos de la superficie se implementan colocando una imagen de rayos de luz en una capa separada, e imitando reflejos dinámicos sincronizados con el movimiento del vidrio mediante
background-attachment: fixedo JavaScript - La UI final combina las capas
.glass,.lighty.drag-me, y agrega esquinas redondeadas, clipping y un color de fondo semitransparente para completar un componente de vidrio copiable
Efecto de panel de vidrio tomado de las UI de juegos
- El objetivo es recrear en HTML el diseño de acrílico esmerilado visto en la experiencia de desarrollo de UI de Forza Horizon 3 y Forza Motorsport 7
- El resultado es un panel de vidrio arrastrable que combina desenfoque de fondo, profundidad en los bordes, reflejos de luz, esquinas redondeadas y una capa de color semitransparente
- Al inicio se ofrece una receta final que se puede copiar y usar directamente, y luego se construye cada efecto paso a paso
Crear desenfoque de fondo con backdrop-filter
- La clave de un buen efecto frosted glass es el desenfoque gaussiano, que desenfoca el fondo para que parezca una pantalla semitransparente
- En CSS se implementa aplicando
blurabackdrop-filter - El elemento de vidrio básico empieza con un
divsimple y la clase.glassbackdrop-filter: blur(10px)-webkit-backdrop-filter: blur(10px)
- En iOS, salvo que se modifiquen configuraciones avanzadas por separado, se necesita
-webkit-backdrop-filter - Como
backdrop-filterrecién obtuvo soporte en navegadores hace relativamente poco, los usuarios de Internet Explorer no podrán experimentar la demo
Crear profundidad con bordes y sombras
- Si solo se aplica
backdrop-filter: blur(10px), el vidrio puede verse plano y monótono - Los bordes se implementan con
box-shadow: inseten lugar deborder: 1px solidborderafecta el tamaño del elemento y la disposición de los elementos hijos- Al usar
box-shadow: inset, los elementos hijos pueden llenar naturalmente el área de contenido del vidrio sin ajustes como márgenes negativos
- Los bordes del vidrio se representan con dos sombras inset blancas semitransparentes
- La primera sombra representa el borde del vidrio visible desde afuera; en el ejemplo aparece en los bordes inferior e izquierdo
- La segunda sombra representa el borde visible a través del vidrio; en el ejemplo aparece en los bordes superior y derecho
- El borde visible a través del vidrio se configura más suave y transparente porque la luz se reduce al atravesarlo
- Agregar un
box-shadowoscuro normal puede dar la sensación de que el vidrio flota físicamente sobre el fondo
Dispersión de la luz y reflejos de superficie
- La sensación de que la luz se propaga dentro del vidrio se expresa de forma simplificada mediante
subsurface scattering - Para implementarlo se vuelve a usar
box-shadow: inset- Efecto de dispersión corto:
inset 0px 0px 10px 5px rgba(255, 255, 255, 0.025) - Efecto de dispersión más profundo:
inset 0px 0px 40px 5px rgba(255, 255, 255, 0.025)
- Efecto de dispersión corto:
- Este efecto se nota mejor al arrastrar el vidrio sobre un fondo oscuro
- Además de la sensación de refracción causada por el fondo desenfocado, también se agrega la característica reflectante de la superficie del vidrio
- Los reflejos de luz se implementan mezclando una imagen de rayos de luz como fondo
- Hay un tutorial de YouTube y una explicación en texto que pueden servir de referencia para crear una imagen similar
- Si se coloca la imagen directamente como
background-imagedel elemento.glass,backdrop-filterla desenfoca, así que se usa una capa separada como::before
Convertir reflejos estáticos en dinámicos
- Si solo se superpone una imagen de rayos de luz, habrá reflejo, pero al mover el vidrio puede parecer que la luz está fija en la superficie del vidrio
- El enfoque con CSS puro agrega
background-attachment: fixeda::before- La implementación es simple, pero puede no funcionar en todas las plataformas
- Para que funcione en todas las plataformas, se imita
background-attachment: fixedcon JavaScript- Manipular
::beforedirectamente desde JavaScript es ineficiente, por lo que se usa un elementodiv.lightseparado - Al elemento objetivo se le agrega el atributo
data-js-background-attachment-fixed
- Manipular
- En cada frame de animación, JavaScript lee el valor de
getBoundingClientRect()del elemento objetivo y actualizabackground-positionen la dirección opuesta a su posición dentro del viewportbackgroundPositionX = -clientRect.xbackgroundPositionY = -clientRect.y
- El bucle repetitivo se ejecuta con
requestAnimationFrame
Estructura final de HTML/CSS
- El HTML final de la versión con JavaScript tiene una estructura en la que dentro de
.glassse colocan.lightpara los reflejos de luz y.drag-mecomo capa de texto/color
Drag Me
.glassse encarga de la forma básica y los efectos visuales del panel de vidrio- Aplica desenfoque de fondo con
backdrop-filtery-webkit-backdrop-filter - Aplica bordes, sombra y efecto de dispersión con varios
box-shadow - Permite que las capas hijas llenen el área del padre con
position: relative - Aplica esquinas redondeadas con
border-radius: 5px - Recorta los elementos hijos para que no sobresalgan de las esquinas redondeadas con
overflow: hidden
- Aplica desenfoque de fondo con
.lightusa la imagen de rayos de luz como fondo repetidobackground-image: url(path/to/light.png)background-repeat: repeatbackground-size: 750pxopacity: 0.075- Llena todo el padre con
position: absolutey offsets0en las cuatro direcciones - Se renderiza detrás de los demás hijos con
z-index: -1
.drag-mecentra el contenido y crea una capa de vidrio semitransparente con colordisplay: flexalign-items: centerjustify-content: centerheight: 30pxbackground-color: rgba(12, 13, 14, 0.75)
Diferencias de la versión sin JavaScript
- La versión sin JavaScript usa
.glass::beforeen lugar de un elemento.lightseparado - Aplica la imagen de rayos de luz a
::beforee implementa reflejos fijos en pantalla conbackground-attachment: fixed - Este enfoque no funciona en todas las plataformas, y la versión con JavaScript lo compensa actualizando directamente
background-position
1 comentarios
Comentarios de Hacker News
Estéticamente me encanta, pero en los bordes hay partes que no cuadran físicamente.
Desde la perspectiva de un desarrollador embebido, se siente un poco desperdiciador. Da la impresión de que cada cliente está calculando cada vez un filtro de desenfoque “costoso” para mezclarlo con una versión borrosa de la imagen de fondo.
Puede que al final no cueste tanto porque usa GPU y está optimizado, pero el desarrollo web actual en general parece ir demasiado hacia lo inflado. Incluso los sitios simples tardan 5 segundos en cargar y le avientan procesamiento pesado al cliente, aunque claro, eso no es culpa del autor de este artículo.
Crecí en la era del módem de 14.4k, así que estoy acostumbrado a pensar que el ancho de banda de red es mucho más escaso y caro que el tiempo de CPU.
Si el cliente puede calcularlo fácilmente, me parece más desperdicio descargar la imagen completa por internet. Para traer esa imagen estás haciendo trabajar routers, servidores y discos lejanos, todo para evitar una sola operación sobre datos que ya están en la RAM del cliente.
Así que o el entretenimiento en sí es un desperdicio, o si no lo es, entonces también está bien usar más cómputo para hacerlo mejor.
De todos modos, para volver a dibujar lo que cambia en la UI ya hace falta cómputo en la GPU, y un desenfoque simple puede agregarse de forma bastante eficiente. Es muy probable que cueste menos que animar objetos del DOM que no están optimizados como capas de GPU.
Viendo que hoy hasta el sitio más simple carga más de 1MB de JavaScript y un montón de rastreadores que se comen la CPU, el desenfoque por estética me parece muy abajo en la lista de desperdicios.
Si hay muchas imágenes en alta resolución, el ancho de banda real de red es finito y, sobre todo en entornos móviles con mala cobertura inalámbrica, claramente rinde peor que calcularlo localmente. Hoy sorprende todo lo que puede hacerse solo con CSS/WebGL; antes para estos efectos hacían falta muchos hacks y rodeos.
Más allá de si el acto en sí es un desperdicio, esta forma de pensar muestra un problema social más grande. ¿Por qué se necesita esto, y por qué se considera malo no tenerlo?
Pensando en la escala de los problemas sociales de hoy, ¿a quién le importaría si un panel de UI está borroso o no?
En Android, mientras veía qué se podía hacer con la nueva API de shaders, alguna vez recreé el efecto Windows 7 Aero Glass y terminé extrayendo una textura parecida de “rayas de luz”.
Al final quedó muy parecido a este artículo, aunque no le puse sombra interior y subí un poco la saturación del fondo borroso.
https://mastodon.social/@grishka/110524476584503201
La verdad, la que hice para el tutorial ni siquiera está tan bien. Me gustan las líneas más definidas de la versión de Windows 7.
También pensé en ajustar la saturación y lo vi en otros ejemplos, pero decidí no usarlo en el artículo. La imagen de la luna que usé no tenía muchos colores, así que probablemente no habría hecho gran diferencia. A quienes quieran crear su propio efecto de vidrio les vendría bien experimentar también con la saturación.
El trabajo en sí es excelente, y también me gusta que lo muestren como una demo interactiva. Es divertido arrastrar la ventana sobre la luna.
Pero no me gusta usar el efecto de vidrio esmerilado en diseño de interfaz de usuario; cuando se agregó a Mac OS me pareció un retroceso. A los diseñadores este efecto los seduce con demasiada facilidad, pero en la práctica nunca es ideal. Sobre todo cuando el contenido detrás del panel es dinámico o lo genera el usuario.
Es como el brushed metal de los 2010s, y me sorprende que se haya filtrado desde Windows Vista hacia todos lados.
Claro que el diseño también afecta la función, pero su propósito principal es hacer más agradable la experiencia del usuario.
Creo que el skeuomorphism hacía las interfaces más agradables que la tendencia minimalista de volver plano todo lo que dominó por más de 10 años. Los adornos visuales que imitan superficies y materiales del mundo real aportan familiaridad y accesibilidad. Incluso en lo práctico, el flat design dificulta distinguir elementos y estados, mientras que en la época de los botones 3D, el brushed metal y el vidrio esmerilado todo era mucho más claro.
Creo que ahora estamos empezando a regresar. Como más diseñadores están evitando la apariencia plana, espero que resurja una UI más amigable para los humanos.
El desenfoque casi nunca es la respuesta correcta, pero a veces sí lo es.
Antes de que CSS soportara
backdrop-bluren 2008, ya se había hecho un experimento en CSS para lograr un efecto similar: https://webdev.andersriggelsen.dk/aero/Consistía en aplicar un efecto de vidrio sobre una imagen de fondo previamente desenfocada y en posición fija: https://webdev.andersriggelsen.dk/aero/bgl.jpg
Rendía mucho mejor que un desenfoque gaussiano en tiempo real, pero seguía teniendo la desventaja de no permitir imágenes de fondo dinámicas
Se podía lograr el efecto de vidrio incluso dentro de marcos que se movían dinámicamente. No recuerdo si se usó
iframe, así que tendría que buscar el código, pero considerando la época, probablemente síEstoy en Windows 10 19045.5131 y Chrome está en la última Version 131.0.6778.86 (Official Build) (64-bit)
El logro técnico es genial, pero me parece una mala UX
El contenido dentro de paneles semitransparentes es más difícil de leer o entender que sobre un fondo sólido uniforme, el contraste con el fondo es bajo e irregular. Además, si algo se mueve por debajo, puede distraer y desorientar
En una buena integración, se ajusta la intensidad del efecto para no recargar demasiado la UI, se comprueba la compatibilidad para evitar adornos extra cuando no hay soporte para blur, y se revisan las capacidades de pantalla y video para no renderizarlo en dispositivos donde la GPU podría no ser suficiente
También hay que revisar las preferencias del usuario para ofrecer colores sólidos con buen contraste a quienes tienen dificultades con fondos complejos, limitar el efecto y el alcance de las sombras según el espacio disponible, y ajustar el blur y la opacidad considerando la complejidad y el contraste del fondo debajo de la zona borrosa
También hace falta asegurar que el blur y las sombras escalen de forma adaptativa según la tipografía. La UX, en esencia, es el diseño de cómo el usuario experimenta la interacción con toda la app, no algo que se determine por una sola elección de estilo
Eso garantizaba la legibilidad del texto incluso en casos extremos con fondo negro. En CSS se puede recrear con la propiedad
text-shadowAun así, en juegos sí tiene más espacio. En especial puede funcionar bien en un HUD, donde no quieres tapar el fondo, que es el área principal con la que interactúa el usuario
Lograr buen contraste es un reto en cualquier elemento de diseño, ya sea un color sólido o un efecto de vidrio
Lo de que lo que ocurre en el fondo distrae y desorienta también es muy subjetivo. Así como se puede bajar la opacidad de un color sólido, también se puede bajar la semitransparencia del vidrio
Es difícil considerar esta crítica como una verdad objetiva, y sí hay formas de integrar este recurso de diseño evitando esos problemas. La captura de Forza se ve bien y, al verla en la práctica, el fondo no resultaba distractor. A cambio, se obtiene una UI más interesante y visualmente agradable que con un fondo sólido. Puede ser más importante en videojuegos, pero también se puede usar con elegancia en diseño de SO y web
Si se necesita mucho contexto, el blur no es una buena opción, y si no se necesita nada de contexto, tampoco lo es
Pero a veces sí es una excelente opción
El ejemplo interactivo está bien, pero habría estado mejor si tuviera un toggle para compararlo o alternarlo con la etapa anterior
En la mayoría de las etapas, la mejora es demasiado sutil y cuesta notar la diferencia
Hay como 10 efectos superpuestos, y salvo que se busque la estética más exigente, unos 7 sobran
Con color de fondo, blur y algo de sombra o borde basta
Ya en la tercera etapa sale una pieza de vidrio bastante decente solo con blur y sombra. Personalmente recomiendo mezclarle además una imagen estática de reflejo de luz. En la mayoría de las aplicaciones no creo que haga falta todo el efecto en JavaScript. Es divertido, pero puede distraer
Solo con blur, sombra y reflejo de luz ya se puede acercar muchísimo a la imagen de Forza de arriba
Creo que esa es una de las razones por las que todos se fueron al diseño plano. Windows Vista y los efectos de vidrio eran geniales, pero tenían un costo computacional alto
El diseño plano es debatible estéticamente y, sobre todo para usuarios mayores, puede ser más difícil de usar que el diseño esqueumórfico [0][1]
Si el realismo puede ayudar a la usabilidad, me parece totalmente válido usar este tipo de efectos en la web
[0]: https://www.tandfonline.com/doi/abs/10.1080/0144929X.2020.18...
[1]: https://www.sciencedirect.com/science/article/abs/pii/S01419...
n <= 3No sé si es por accesibilidad, rendimiento, mantenibilidad o por alguna otra razón
CSS es por mucho el área más débil de mis habilidades de desarrollo, así que no conozco en absoluto las buenas ni las malas prácticas
Es interesante porque se siente como si hubiéramos dado una vuelta completa
Uno de los primeros demos de CSS, para CSS 1, fue precisamente un efecto de vidrio escarchado: https://meyerweb.com/eric/css/edge/complexspiral/glassy.html
La verdad, está bastante impresionante. Siempre es un gusto ver lo creativo y potente que puede ser CSS.
Aun así, siento que en HTML/CSS hay un nivel que jamás voy a entender del todo. Este demo es justo eso: esta persona está creando una ventana escarchada y yo todavía no puedo ni centrar un solo
divdivmás muchas veces es una buena idea.Si ves la mayoría de los sitios web modernos, están apilados como un enorme montón de
div. Si quieres undivcentrado, suele ser relativamente fácil crear otrodivdentro que ocupe todo el espacio donde quieres centrarlo.Muchos trucos visuales son parecidos, pero este ejemplo es especialmente impresionante por lo limpio que está
No es exactamente vidrio escarchado, pero probé poner un efecto de cristal en la barra lateral de https://www.gyan.dev/ffmpeg/builds/