Ir al contenido
angel.library

Liquid Glass

Liquid Glass es el lenguaje de diseño que Apple presentó en la WWDC 2025, su cambio visual más grande desde iOS 7. Se aplica de forma unificada en iOS 26, iPadOS 26, macOS Tahoe 26, tvOS 26, watchOS 26 y visionOS.

La idea es un material dinámico que imita el vidrio real: translucidez, refracción, profundidad y reacción al movimiento, adaptándose al contenido y a la luz que tiene debajo.

Es la pregunta obligada, porque a primera vista se parecen:

GlassmorphismLiquid Glass
Qué hace con el fondoLo desenfocaLo desenfoca y lo refracta, como un cristal grueso
ReacciónEstáticoResponde al movimiento y a la interacción
AdaptaciónOpacidad fijaSe ajusta al contenido y a la luz de debajo
OrigenTécnica de CSSSistema definido por un fabricante, con APIs propias
BordesLínea clara de 1 pxCantos que concentran y curvan la luz

En resumen: glassmorphism simula una lámina; Liquid Glass simula un volumen de vidrio.

Apple publicó recursos de diseño actualizados para iOS 26, iPadOS 26 y macOS Tahoe 26. SwiftUI incorpora modificadores de vista específicos para materiales de vidrio, y UIKit tiene las APIs equivalentes para quien trabaja de forma imperativa.

Lo importante para un equipo de producto: en las plataformas de Apple el material es del sistema, no algo que se reimplementa. Adoptarlo es usar los componentes nativos y dejar que el sistema resuelva el resto.

En la web no existe el material: hay que aproximarlo. Se puede llegar bastante lejos combinando desenfoque, saturación, un canto que refleje luz y un brillo que se mueva con el puntero.

Material líquido Desenfoque, saturación y un canto que atrapa la luz.
src/styles/liquid-glass.css
.liquid {
/* Degradado en la propia superficie: simula el grosor del vidrio. */
background: linear-gradient(
135deg,
rgb(255 255 255 / 0.22),
rgb(255 255 255 / 0.08)
);
/* saturate() es lo que separa esto de un desenfoque plano:
revive el color de lo que hay detrás, como el vidrio real. */
backdrop-filter: blur(18px) saturate(180%);
-webkit-backdrop-filter: blur(18px) saturate(180%);
border: 1px solid rgb(255 255 255 / 0.35);
border-radius: 22px;
box-shadow:
/* Canto superior iluminado y canto inferior tenue: el volumen. */
inset 0 1px 0 rgb(255 255 255 / 0.55),
inset 0 -1px 0 rgb(255 255 255 / 0.15),
0 12px 40px rgb(0 0 0 / 0.4);
}

Las dos piezas que lo alejan del glassmorphism clásico son saturate() en el backdrop-filter y el par de sombras internas que iluminan los cantos.

Para la parte reactiva, un brillo que sigue al puntero:

src/styles/liquid-glass.css
.liquid {
position: relative;
overflow: hidden;
}
.liquid::after {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(
circle at var(--x, 50%) var(--y, 50%),
rgb(255 255 255 / 0.25),
transparent 45%
);
opacity: 0;
transition: opacity 0.3s;
pointer-events: none;
}
.liquid:hover::after {
opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
.liquid::after {
display: none;
}
}
src/scripts/liquid.ts
document.querySelectorAll<HTMLElement>(".liquid").forEach((panel) => {
panel.addEventListener("pointermove", (event) => {
const caja = panel.getBoundingClientRect()
panel.style.setProperty("--x", `${event.clientX - caja.left}px`)
panel.style.setProperty("--y", `${event.clientY - caja.top}px`)
})
})

Todo lo del glassmorphism aplica multiplicado: blur(18px) saturate(180%) es más caro que un desenfoque solo, y añadir un brillo animado encima significa recomponer en cada movimiento del puntero.

Reglas para no arruinar el rendimiento:

  • Úsalo en una o dos superficies fijas, nunca en elementos de una lista.
  • El seguimiento del puntero debe limitarse con requestAnimationFrame si la superficie es grande.
  • Da siempre una alternativa sólida con @supports not (backdrop-filter: blur(1px)).
  • Sí en aplicaciones nativas del ecosistema Apple: ahí es lo que el sistema espera y lo resuelve el sistema.
  • Sí en una web que quiera sentirse afín a ese ecosistema, en superficies puntuales.
  • No como sistema visual de un producto multiplataforma: imitarlo fuera de Apple sale caro en rendimiento y siempre queda a medias.
  • No en interfaces densas de datos.