Glassmorphism✨ Premium

Glass Morphing Button

A glass button that changes shape on hover, in pure CSS: side padding 36 → 52 px, corners 14 → 20 px, violet border and inner glow, 5% zoom — it goes from 161 × 46 to 203 × 53 px on screen and stretches toward the hand, over two colored glows floating behind it.

CSSButtonMorph

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

"See the cabins" button over the boat video — river cruise website — Glass Morphing Button example 1

① "See the cabins" button over the boat video — river cruise website

WhenA Rhône cruise page: the boat video in the background, a single glass button leads to the cabin plan.
WhyThe button stays transparent over the video and only grows on hover: it doesn't hide the landscape but makes itself known as you approach. Centered under the title, it stretches both ways at once and keeps the page's axis.
SettingsThe effect's scene (300 × 180 px) placed bottom center on the painted video (sunset, hills, shimmering river, boat moving along over 26 s); glows recolored amber #f59e0b and light cyan #22d3ee; original button padding, corners, border, violet glow and zoom; label "See the cabins".
"Book a test ride" button over a cargo bike video — bike shop website — Glass Morphing Button example 2

② "Book a test ride" button over a cargo bike video — bike shop website

WhenAn electric cargo bike page: the video of a parent loading two children in the background, a single glass button to book a test ride in the shop.
WhyThe video is the sales pitch: the glass keeps it visible, and the stretch on hover gives weight to the page's only action. Left-aligned under the text, the button grows toward the bike, on the free side; the label only slides a few pixels with the padding.
SettingsStreet painted in CSS (facades, scrolling road markings, cargo bike with turning wheels, two children's helmets in the box); dark veil on the left for the text; effect scene bottom left, teal #14b8a6 and amber glows; original button, label "Book a test ride".
"Start the 360° tour" button over the living-room photo — estate agency listing — Glass Morphing Button example 3

③ "Start the 360° tour" button over the living-room photo — estate agency listing

WhenA flat listing: the living-room photo full size, the glass button opens the virtual tour.
WhyA solid button would hide part of the room; the glass keeps it readable and the growth on hover confirms it is clickable over a busy photo — a sofa, a table, a rug, a window behind it.
SettingsLiving room painted in CSS (bright window, parquet in perspective, sofa, rug, plant); effect scene bottom right; button background switched to 22% dark brown (30% on hover) instead of 8% white, because the photo is light; orange #f4a261 and sea-green #2a9d8f glows; label "Start the 360° tour".

How it works

A real <button class="glass-morph-btn"> placed in a small 300 × 180 px .glass-btn-scene. Behind it, two glows — a 100 px violet #8b5cf6 top left, an 80 px cyan #06b6d4 bottom right — blurred at 40 px and animated by glassBtnOrb (5 s, the second one reversed): since the keyframes are symmetrical, reversing gives the same path: they slide together 20 px right and 15 px up, then come back. The button is 8% white with backdrop-filter: blur(20px), a 15% white border, 14 px corners, a white uppercase label (14.4 px, weight 600, 1 px letter spacing), a black 0 4px 16px shadow and, in ::before, a 135° highlight from 15% white to transparent. The dark #0a0a0f background comes from the .demo-preview frame shipped with the code: the scene itself is transparent.

On hover, everything changes at once over 0.4 s (transition: .4s cubic-bezier(.4, 0, .2, 1), applied to all properties): padding 14px 36px → 16px 52px, corners 14 → 20 px, background at 12%, violet border at 40%, violet 0 8px 32px shadow plus an inset 0 0 20px inner glow, and scale(1.05). Measured in Chromium: 161 × 46 px at rest, a 193 × 50 px box on hover, i.e. 203 × 53 px on screen with the zoom; in Firefox, 157 × 48 → a 189 × 52 px box, 198 × 55 px on screen (the label renders slightly narrower there). On click, :active drops to scale(.98). Since it is the padding that grows, the button really takes up space: centered, it stretches both ways; left-aligned, it grows to the right and pushes whatever follows it on the line.

The blur is declared twice, backdrop-filter: blur(20px) and -webkit-backdrop-filter: blur(20px), and it is not a repeat: Safari before version 18 (including iOS 17 and earlier) only reads the prefixed form, and without it would show a merely translucent button, with no frosting. Otherwise the button depends on nothing: no JavaScript, no dependency, no site variable.

Accessibility

  • Keyboard: it is a <button>, it takes focus with Tab and activates with Enter or Space. The stretch, however, only exists on hover: with the keyboard the button keeps its resting size with the browser's default focus ring. Add .glass-morph-btn:focus-visible to the :hover rule so focus produces the same shape, and keep a visible outline (outline: 2px solid #a78bfa; outline-offset: 3px).
  • Touch: on mobile there is no hover before the finger. On the first tap most mobile browsers apply :hover and leave it in place after release, so the button stays stretched until you touch elsewhere. To limit the stretch to pointer devices, wrap the rule in @media (hover: hover) { … }.
  • No prefers-reduced-motion in the code: the glows keep floating and the 0.4 s transition stays active under emulation. The stretch is user-triggered and short; add @media (prefers-reduced-motion: reduce) { .glass-morph-btn { transition: none } .glass-btn-bg-1, .glass-btn-bg-2 { animation: none } } for a state change without motion.
  • Contrast: white label measured between 6.5:1 and 10:1 on the button depending on the glow passing behind. On a light photo, 8% white is no longer enough: the real-estate scene switches the button background to 22% dark brown. The label is uppercased by CSS (text-transform): write it normally in the HTML and screen readers will read it as a word, not letter by letter.

Browser compatibility

CSS only: backdrop-filter and -webkit-backdrop-filter, filter: blur(), transition on padding, border-radius, box-shadow (including inset) and transform, @keyframes. Zero JavaScript, zero dependency. Backdrop blur: Chrome 76+, Edge 79+, Firefox 103+, Safari 9+ with the prefix (declared in the code), unprefixed since Safari 18. Measured in Chromium 151 and Firefox 153: same computed values at rest and on hover (padding, corners, violet border, scale(1.05)). Firefox and WebKit 26.5 under Playwright recognize the blur (blur(20px) computed) but their automated screenshots do not paint it, even on a minimal test: the frosting was only seen in Chromium.

Chrome 76+✓ Full
Firefox 103+✓ Full (blur not verifiable in automated screenshots)
Safari 9+✓ Full (with the -webkit- prefix in the code)
Edge 79+✓ Full
Mobile iOS 9+✓ Stretches on first tap, stays stretched until the next touch
Android Chrome 76+✓ Same touch behavior as iOS

Without backdrop blur, the button stays an 8% white veil over the glows, and the stretch works the same: transitions on padding, border-radius and box-shadow exist in every current browser. Over a sharp photo, plan a more opaque background inside @supports not (backdrop-filter: blur(1px)).

The code

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

index.html — structure
<div class="demo-preview">
  <div class="glass-btn-scene">
    <div class="glass-btn-bg-1"></div>
    <div class="glass-btn-bg-2"></div>
    <button class="glass-morph-btn">…</button>
  </div>
</div>
Unlock the full code — $9.90/mo incl. tax

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

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Stretch (CSS — padding: 14px 36px → :hover { padding: 16px 52px }) +16 px on each side, +2 px in height The gap between the two paddings is what makes the "morphing". 16px 64px for a stronger stretch; keep the same height (14 → 14 px) for a button that only grows in width. This padding change moves neighboring elements: center the button or give it a fixed width if it sits in a row.
Corner shape (CSS — border-radius: 14px → 20px) 14 px then 20 px 999px on hover gives a pill; the reverse (20 → 8 px) gives a button that hardens under the hand. The transition interpolates both values over 0.4 s.
Hover color (CSS — border-color, box-shadow in rgba(139,92,246,…)) violet at 40% (border), 30% (shadow), 10% (inner glow) Replace the three occurrences of 139, 92, 246 with your brand color. The inner glow (inset 0 0 20px) is what makes the glass look lit; remove it for a quieter hover.
Zoom (CSS — transform: scale(1.05) on hover, scale(.98) on click) +5% then −2% The zoom adds to the padding stretch: at 1.05, the 193 px button looks 203 px wide. Use scale(1) so only the stretch plays, with no text blur during the growth.
Glass (CSS — background: rgba(255,255,255,.08), backdrop-filter: blur(20px)) 8% white, 20 px blur Over a light photo or video, switch to a dark tint (rgba(30,25,20,.22)); over a very busy video, raise the blur to 28 px so the label doesn't shimmer over the details.
Glows behind the button (CSS — .glass-btn-bg-1, .glass-btn-bg-2, glassBtnOrb 5s) 100 px violet and 80 px cyan, 40 px blur, 5 s Over an already colorful background, keep them to tint the glass in brand colors or remove them. The dark background comes from .demo-preview: if you remove it, give .glass-btn-scene a background or place it over your image.

FAQ

Because the stretch goes through the inner padding (36 → 52 px on each side): the button's box really grows, from 161 to 193 px wide (measured in Chromium). In a line of text or a row of buttons, its neighbors shift by 32 px. That is intended here — it is what keeps the label still in the middle while the glass spreads — but it also means a layout recalculation on every frame of the transition. Two ways around it: center the button in a slightly wider container (as in the cruise scene), or give it a fixed width and only animate transform: scaleX() on a background pseudo-element.
It works — it is a real <button> — but the stretch is tied to hover. With a finger, on most mobile browsers, the first tap triggers both the click and :hover, which stays applied after release: the button stays stretched. With the keyboard nothing stretches, only the focus ring appears. Add :focus-visible to the hover rule and wrap that rule in @media (hover: hover) for clean behavior on all three.
It provides the #0a0a0f background on which the glows and the glass read; the .glass-btn-scene itself is transparent. If you place the button over your own image or video, you can remove that frame: the glass will blur your image. If you place it on a white page with nothing behind, keep the frame or give the scene a background, otherwise the white label disappears.