Glassmorphism✨ Premium

Rain on Glass

A slightly frosted pane (3 px blur) in front of a city at dusk: a drop is born at the top every 0.4 to 1.2 s, falls in 3 to 7 s while speeding up, drifts a few pixels and leaves a 40 px trail — five to nine drops at once, measured in all three engines.

JSAnimationRain

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Glassmorphism has 47 effects, including 6 free. Explore the category →

3 usage examples

Rain alert for the Saturday market — a town hall's website — Rain on Glass example 1

① Rain alert for the Saturday market — a town hall's website

WhenBanner on the open-air market page: showers likely between 10 am and noon, the market goes ahead and the covered hall is open.
WhyThe wet pane announces the rain before anyone reads: you see the stalls and the church blurred behind glass where drops run down. The tone stays calm — no red warning icon, no blinking banner — which suits practical information rather than a weather warning. The text itself sits under the picture, sharp.
Settings540 × 236 px banner scene; the original city replaced by the market square (four stalls with striped awnings, church, houses) under the 3 px pane; drops enlarged ×2.2 through transform and 3 px trails to stay visible at that size. For the capture, the rain starts with drops already on their way (in the sold code, the pane is dry on load and fills up in 3 to 4 s).
Cover of an urban crime novel — a publisher's page — Rain on Glass example 2

② Cover of an urban crime novel — a publisher's page

WhenLaunch page of a noir novel: the cover shows a city at night behind a pane where the rain runs down.
WhyRain on a window at night sets the genre's mood in one moving image: blurred lit windows, a red neon sign, sharp drops in the foreground. The cover stays readable — title and author above the pane — and the page stands out from still covers without adding a video.
SettingsCover-format scene, 212 × 316 px; towers, windows and neon drawn inside .lg-rain-city; title and author set above the pane (z-index: 3). Same drops enlarged ×2.2.
Match postponed, waterlogged pitch — an amateur rugby club's website — Rain on Glass example 3

③ Match postponed, waterlogged pitch — an amateur rugby club's website

WhenAnnouncement at the top of the club's home page: Sunday's match is postponed, new date to come.
WhyThe drops explain the reason without an apology: soaked pitch, puddles, floodlights in the drizzle. Supporters understand at a glance that it is not a forfeit. The white card in front carries the precise information.
SettingsFull-frame 540 × 360 px scene: stand, floodlights, posts and muddy pitch under the pane; announcement card and club name above the pane. Drops enlarged ×2.2.

How it works

The .lg-rain-scene scene (260 × 180 px, 14 px corners, a sky graded from night blue #1e3a5f to light blue #6b9fd4) holds a city skyline — nine buildings 10 to 22 px wide, in 60% slate blue — and, in front of it, a .lg-rain-glass pane covering the whole scene with backdrop-filter: blur(3px) (and -webkit-) on layer 1: the city is seen through misted glass. Drops and their trails sit on layer 2, on the pane, hence sharp.

The script starts the rain when 30% of the scene enters the screen (IntersectionObserver, once). It then creates a drop, then the next one 0.4 to 1.2 s later, endlessly. Each drop is a div 4 to 10 px wide and 1.3 times taller, tear-shaped (border-radius: 50%/60% 60% 40% 40%), filled with a white → pale blue → transparent radial gradient with an inner highlight. It starts 10 px above the edge and falls to 10 px below the bottom in 3 to 7 s, on a squared curve — slow at first, fast at the end — drifting sideways by ±15 px at most (sin(π·h)). Its trail (2 px wide, up to 40 px long) follows it and fades as it falls. At the bottom, drop and trail are removed from the page.

Measured every 2 s after start: 3, 6, 7, 9, 8, 6 drops in Chromium 151; 4, 7, 6, 6, 7, 6 in Firefox 153; 3, 6, 5, 6, 6, 7 in WebKit 26.5 — the steady state settles within 3 to 4 s and hovers around six drops. No console error, no dependency. Its only measured weakness is that the rain never stops, even off screen (6 drops still active 3 s after scrolling the scene out of view) — see accessibility and the FAQ to pause it.

Accessibility

  • Endless animation: the rain runs as long as the page is open, and nothing is provided for prefers-reduced-motion or to pause it. An automatic animation lasting more than 5 s must be stoppable (WCAG 2.2.2). The simplest fix: do not start it when the user asked for less motion — in the script, replace a.observe(e) with matchMedia('(prefers-reduced-motion: reduce)').matches || a.observe(e); the pane and the city remain, dry.
  • Decoration, not information: the drops tell a screen reader nothing, and must not carry the message alone. Add aria-hidden="true" on the scene, and give the message as text (“Showers likely 10 am to noon”, “Match postponed”) — in the three scenes on this page, the text sits above or beside the pane, never behind it.
  • Text on the pane: text placed inside the scene without a z-index goes under the pane and comes out blurred. Put it above (position: absolute; z-index: 3) or outside the scene; over the sky, keep a dark background behind the letters, since the white drops pass over them.
  • Off screen: the loop keeps running when the scene is no longer visible (measured). No effect for the user, but wasted work on a phone — see the FAQ to stop it out of view.

Browser compatibility

JS: IntersectionObserver, requestAnimationFrame, setTimeout, createElement. CSS: backdrop-filter (and -webkit-), radial gradients, elliptical border-radius. Zero dependencies. Measured in Chromium 151, Firefox 153 and WebKit 26.5: same rhythm and same number of drops within one or two, city blurred by 3 px in all three, no console error.

Chrome 76+✓ Full
Firefox 55+✓ Full (misted pane from Firefox 103)
Safari 12.1+✓ Full
Edge 79+✓ Full
Mobile iOS 12.2+✓ Full
Android Chrome 76+✓ Full

Without backdrop-filter (Firefox before 103), the city is sharp behind the pane: drops fall normally, only the misted-glass effect disappears. Without IntersectionObserver (Safari before 12.1), the rain never starts: the scene stays a dry city at dusk.

The code

HTML structure to paste into your page (the CSS + JS come with Premium):

index.html — structure
<div class="demo-preview">
  <div class="lg-rain-scene" data-rain-scene="">
    <div class="lg-rain-glass"></div>
    <div class="lg-rain-city">
      <div class="lg-rain-building" style="width:12px;height:35px"></div>
      …
    </div>
    <!-- div.lg-raindrop + div.lg-raindrop-trail, added then removed by the script -->
  </div>
</div>
Unlock the full code — $9.90/mo incl. tax

The full HTML + CSS + JS of Rain on Glass, ready to paste — plus all 840 effects. Or $299 once, lifetime access.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Drop size (JS — n = 4 + 6 * Math.random(); or CSS — .lg-raindrop { transform: scale(2) }) 4 to 10 px wide On a large scene, the original drops are barely visible. Change the formula (8 + 10 * Math.random()) or enlarge them in CSS: the script does not write transform, so a scale applies as is (with transform-origin: 50% 100%).
Rhythm (JS — setTimeout(t, 400 + 800 * Math.random())) one drop every 0.4 to 1.2 s, about six at once 150 + 300 * Math.random() for a downpour (around fifteen drops), 1500 + 2000 * Math.random() for a sparse drizzle.
Falling speed (JS — o = 3e3 + 4e3 * Math.random()) 3 to 7 s to cross the pane, speeding up 1500 + 1500 * Math.random() for driving rain. The squared curve (h * h) gives the acceleration; plain h would fall at constant speed.
Drift and trail (JS — l = 30 * (Math.random() - .5), Math.min(40, …)) ±15 px drift, trail up to 40 px 0 for drops falling straight, 60 for a wind-lashed window. The maximum trail length is set in Math.min(40, p - r).
Pane mist (CSS — .lg-rain-glass { backdrop-filter: blur(3px) }) 3 px 1 px leaves the city almost sharp, 8 px turns it into patches of light. Add background: rgba(255,255,255,.06) to the pane for milkier glass.
Landscape behind the pane (HTML — .lg-rain-city and the inline .lg-rain-buildings) nine slate-blue buildings against a graded sky Replace them with any content or a picture (an <img> in position: absolute; inset: 0; object-fit: cover inside the scene, before the pane). Everything under the pane is blurred, everything above stays sharp.

FAQ

By keeping the observer instead of disconnecting it. In the script, replace the callback with function (x) { v = x[0].isIntersecting; v && !n && (n = !0, t()) }, remove a.disconnect(), declare var v = !1 just before function t(), and at the top of t() add if (!v) { n = !1; return }: the loop stops as soon as the scene leaves the screen and restarts when it comes back (drops in flight finish their fall). Measured with this change: 5 drops in steady state, 0 after 7.5 s out of view, 4 three seconds after coming back on screen — against 6 drops still active out of view with the original code.
No. Each drop is a small white and pale blue gradient with a highlight: it reads as a drop, but does not magnify or flip what is behind it, and its trail is a light streak that fades, not a wiped patch of glass. Drops do not zigzag and do not merge. Real refraction needs WebGL rendering that copies the picture into every drop — much heavier. Here, the effect relies on the contrast between the blurred city and the sharp drops, and costs a few divs.
Yes: the script walks every [data-rain-scene], each gets its own observer and loop, and starts when it reaches the screen. Count about six drops, so a dozen elements, per scene; each drop updates its position every frame, which stays light for two or three scenes.