4 puntos por GN⁺ 2024-11-25 | 1 comentarios | Compartir por WhatsApp
  • 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-filter junto con -webkit-backdrop-filter para 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: fixed o JavaScript
  • La UI final combina las capas .glass, .light y .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 blur a backdrop-filter
  • El elemento de vidrio básico empieza con un div simple y la clase .glass
    • backdrop-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-filter recié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: inset en lugar de border: 1px solid
    • border afecta 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-shadow oscuro 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)
  • 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-image del elemento .glass, backdrop-filter la 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: fixed a ::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: fixed con JavaScript
    • Manipular ::before directamente desde JavaScript es ineficiente, por lo que se usa un elemento div.light separado
    • Al elemento objetivo se le agrega el atributo data-js-background-attachment-fixed
  • En cada frame de animación, JavaScript lee el valor de getBoundingClientRect() del elemento objetivo y actualiza background-position en la dirección opuesta a su posición dentro del viewport
    • backgroundPositionX = -clientRect.x
    • backgroundPositionY = -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 .glass se colocan .light para los reflejos de luz y .drag-me como capa de texto/color

  Drag Me

  • .glass se encarga de la forma básica y los efectos visuales del panel de vidrio
    • Aplica desenfoque de fondo con backdrop-filter y -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
  • .light usa la imagen de rayos de luz como fondo repetido
    • background-image: url(path/to/light.png)
    • background-repeat: repeat
    • background-size: 750px
    • opacity: 0.075
    • Llena todo el padre con position: absolute y offsets 0 en las cuatro direcciones
    • Se renderiza detrás de los demás hijos con z-index: -1
  • .drag-me centra el contenido y crea una capa de vidrio semitransparente con color
    • display: flex
    • align-items: center
    • justify-content: center
    • height: 30px
    • background-color: rgba(12, 13, 14, 0.75)

Diferencias de la versión sin JavaScript

  • La versión sin JavaScript usa .glass::before en lugar de un elemento .light separado
  • Aplica la imagen de rayos de luz a ::before e implementa reflejos fijos en pantalla con background-attachment: fixed
  • Este enfoque no funciona en todas las plataformas, y la versión con JavaScript lo compensa actualizando directamente background-position

1 comentarios

 
GN⁺ 2024-11-25
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.

    • Parece que cada quien tiene sus propios sesgos sobre qué considera un desperdicio.
      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.
    • Incluso los sitios web que en lo técnico pueden verse como “desperdiciadores” terminan usándose, en la práctica, sobre todo para entretenimiento puro.
      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.
    • Desde la perspectiva humana parece desperdicio, como “recalcular en grande unos gráficos ya renderizados”, pero técnicamente no necesariamente lo es.
      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.
    • Me parece que enviar por red tanto la imagen desenfocada como la original es justo la forma en que se ha hecho desarrollo web durante los últimos 20 años.
      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.
    • Creo que ya va siendo hora de aceptar seriamente que muchas tecnologías del tipo “oh, se ve padre, seguro yo/nosotros lo necesitamos” no tienen lugar en este mundo.
      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

    • Está muy padre. La textura de rayas de luz de verdad puede hacer mucho por este efecto.
      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.

    • No entiendo por qué no sería “ideal”. En diseño visual, más que un propósito práctico, pesa mucho el gusto personal sobre qué se ve bien.
      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.
    • No soy diseñador de UI, así que lo pregunto en serio: ¿el problema es usar efectos estéticos como vidrio esmerilado o brushed metal en el diseño de UI en sí, o que algunos diseñadores, al intentar crear interfaces así, terminaron perdiendo las pistas visuales que indican dónde están los controles y para qué sirven?
    • Llevo años poniendo un poco de transparencia en la ventana del terminal, y ahora me está haciendo reconsiderarlo.
    • El brushed metal no afecta el contexto de la información. El desenfoque sí ofrece contexto graduable.
      El desenfoque casi nunca es la respuesta correcta, pero a veces sí lo es.
    • Irónicamente, las versiones anteriores de macOS también usaban bastante brushed metal
  • Antes de que CSS soportara backdrop-blur en 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

    • En una etapa aún más temprana se llevó esto un paso más allá usando un archivo Flash como fondo
      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í
    • La ventana flotante no se actualiza después de la posición inicial
      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

    • Es difícil generalizar como “mala UX” a partir de un solo efecto visual. Depende mucho de cómo se integre
      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
    • Windows Vista resolvía este problema aplicando a las letras negras sobre vidrio escarchado un contorno tipo sombra blanca
      Eso garantizaba la legibilidad del texto incluso en casos extremos con fondo negro. En CSS se puede recrear con la propiedad text-shadow
    • Por eso no uso este efecto en todo mi sitio. Porque es más difícil lograr una buena UX
      Aun 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
    • Si el problema es el bajo contraste, basta con oscurecer más el fondo o el tinte del vidrio y aclarar el contenido en primer plano, o al revés
      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
    • El blur es una forma de ocultar información mientras se conserva cierta cantidad ajustable de contexto
      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

    • De acuerdo. En móvil, después de la segunda etapa casi no se nota diferencia o directamente no se distingue
  • 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

    • Quienes quieran un efecto de vidrio menos pesado pueden elegir del tutorial lo que les sirva
      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
    • Es interesante que la mayoría de los comentarios principales hablen del desperdicio
      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...
    • Me pregunto por qué se considera que el límite de efectos superpuestos es n <= 3
      No 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
    • ¿No se te pasó la parte donde el autor explicó que apuntaba a la estética más exigente?
  • 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 div

    • Cuando estaba aprendiendo cómo funciona el desarrollo web, aprendí por las malas que agregar un div má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 un div centrado, suele ser relativamente fácil crear otro div dentro 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/

    • En PC, el sitio se ve muy agradable y bonito