20 CSS Social Buttons17 / 20
Glassmorphic Social Buttons over an Image
Frosted social buttons floating over a photograph: backdrop-filter blur with a saturation boost, a hairline inner highlight along the top edge, and a translucent border that reads as glass thickness. A @supports block declares a solid fallback first, so browsers without backdrop-filter get an opaque button instead of an unreadable one.
Published
The code
<div class="soc-17">
<div class="soc-17__stage">
<img class="soc-17__bg" src="https://images.unsplash.com/photo-1518495973542-4542c06a5843?w=1600&q=70&auto=format&fit=crop" alt="" width="1600" height="1000" loading="lazy" decoding="async">
<div class="soc-17__scrim" aria-hidden="true"></div>
<div class="soc-17__glass">
<p class="soc-17__eyebrow">Photograph series</p>
<h2 class="soc-17__title">Golden hour, Fitzroy Gardens</h2>
<p class="soc-17__meta">Print available · Sam Rivera</p>
<div class="soc-17__row">
<a class="soc-17__btn" style="--brand:#e1306c" href="https://example.com/samrivera" target="_blank" rel="noopener">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2"><rect x="3.6" y="3.6" width="16.8" height="16.8" rx="5"/><circle cx="12" cy="12" r="3.9"/><circle cx="17.1" cy="6.9" r="1.15" fill="currentColor" stroke="none"/></svg>
<span>Instagram</span>
</a>
<a class="soc-17__btn" style="--brand:#0f1419" href="https://example.com/samrivera" target="_blank" rel="noopener">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round"><path d="M5 5.5 19 18.5"/><path d="M19 5.5 5 18.5"/></svg>
<span>Post</span>
</a>
<a class="soc-17__btn soc-17__btn--icon" href="https://example.com/share" target="_blank" rel="noopener" aria-label="Share this photograph">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="17.5" cy="5.5" r="2.6"/><circle cx="6.5" cy="12" r="2.6"/><circle cx="17.5" cy="18.5" r="2.6"/><path d="m8.9 10.7 6.2-3.6"/><path d="m8.9 13.3 6.2 3.6"/></svg>
</a>
</div>
</div>
</div>
</div><div class="soc-17">
<div class="soc-17__stage">
<img class="soc-17__bg" src="https://images.unsplash.com/photo-1518495973542-4542c06a5843?w=1600&q=70&auto=format&fit=crop" alt="" width="1600" height="1000" loading="lazy" decoding="async">
<div class="soc-17__scrim" aria-hidden="true"></div>
<div class="soc-17__glass">
<p class="soc-17__eyebrow">Photograph series</p>
<h2 class="soc-17__title">Golden hour, Fitzroy Gardens</h2>
<p class="soc-17__meta">Print available · Sam Rivera</p>
<div class="soc-17__row">
<a class="soc-17__btn" style="--brand:#e1306c" href="https://example.com/samrivera" target="_blank" rel="noopener">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2"><rect x="3.6" y="3.6" width="16.8" height="16.8" rx="5"/><circle cx="12" cy="12" r="3.9"/><circle cx="17.1" cy="6.9" r="1.15" fill="currentColor" stroke="none"/></svg>
<span>Instagram</span>
</a>
<a class="soc-17__btn" style="--brand:#0f1419" href="https://example.com/samrivera" target="_blank" rel="noopener">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round"><path d="M5 5.5 19 18.5"/><path d="M19 5.5 5 18.5"/></svg>
<span>Post</span>
</a>
<a class="soc-17__btn soc-17__btn--icon" href="https://example.com/share" target="_blank" rel="noopener" aria-label="Share this photograph">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="17.5" cy="5.5" r="2.6"/><circle cx="6.5" cy="12" r="2.6"/><circle cx="17.5" cy="18.5" r="2.6"/><path d="m8.9 10.7 6.2-3.6"/><path d="m8.9 13.3 6.2 3.6"/></svg>
</a>
</div>
</div>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600&display=swap');
.soc-17 {
--fg: #ffffff;
--muted: rgb(255 255 255 / .78);
--plate: rgb(255 255 255 / .12);
--edge: rgb(255 255 255 / .24);
--ring: #ffffff;
--sans: "Geist",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: #0c1013;
color: var(--fg);
font-family: var(--sans);
-webkit-font-smoothing: antialiased;
}
.soc-17[data-theme="light"] {
--plate: rgb(255 255 255 / .3);
--edge: rgb(255 255 255 / .5);
}
.soc-17,
.soc-17 *,
.soc-17 *::before,
.soc-17 *::after {
box-sizing: border-box;
}
.soc-17__stage {
position: relative;
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.25rem,5vw,3.5rem);
overflow: hidden;
}
.soc-17__bg {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
object-fit: cover;
background: #1a2228;
}
.soc-17__scrim {
position: absolute;
inset: 0;
background: linear-gradient(160deg,rgb(6 10 14 / .35),rgb(6 10 14 / .68));
}
.soc-17__glass {
position: relative;
inline-size: min(30rem,100%);
padding: clamp(1.5rem,4vw,2.25rem);
border-radius: 1.5rem;
border: 1px solid var(--edge);
background: var(--plate);
box-shadow: inset 0 1px 0 rgb(255 255 255 / .35), 0 30px 60px -30px rgb(0 0 0 / .8);
-webkit-backdrop-filter: blur(20px) saturate(170%);
backdrop-filter: blur(20px) saturate(170%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.soc-17__glass {
background: rgb(14 18 22 / .88);
}
.soc-17__btn {
background: rgb(255 255 255 / .16);
}
}
.soc-17__eyebrow {
margin: 0 0 .5rem;
font-size: .72rem;
font-weight: 600;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--muted);
}
.soc-17__title {
margin: 0 0 .3rem;
font-size: clamp(1.2rem,1rem + 1.1vw,1.6rem);
font-weight: 600;
letter-spacing: -.03em;
text-wrap: balance;
}
.soc-17__meta {
margin: 0 0 1.6rem;
font-size: .85rem;
color: var(--muted);
}
.soc-17__row {
display: flex;
flex-wrap: wrap;
gap: .6rem;
}
.soc-17__btn {
display: inline-flex;
align-items: center;
gap: .5rem;
min-block-size: 2.875rem;
padding: 0 1.1rem;
border-radius: .9rem;
border: 1px solid var(--edge);
background: rgb(255 255 255 / .1);
color: var(--fg);
text-decoration: none;
font-size: .9rem;
font-weight: 550;
min-inline-size: 0;
box-shadow: inset 0 1px 0 rgb(255 255 255 / .3);
-webkit-backdrop-filter: blur(10px) saturate(150%);
backdrop-filter: blur(10px) saturate(150%);
transition: background-color .22s ease, translate .22s cubic-bezier(.16,1,.3,1), border-color .22s ease;
}
.soc-17__btn--icon {
padding: 0;
inline-size: 2.875rem;
justify-content: center;
}
.soc-17__btn svg {
inline-size: 1.15rem;
block-size: 1.15rem;
}
.soc-17__btn:hover {
background: rgb(255 255 255 / .2);
translate: 0 -2px;
border-color: rgb(255 255 255 / .42);
}
.soc-17__btn:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.soc-17__btn {
transition-duration: 1ms;
}
.soc-17__btn:hover {
translate: none;
}
}
@media (forced-colors: active) {
.soc-17__glass,
.soc-17__btn {
background: Canvas;
color: CanvasText;
border: 1px solid CanvasText;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
.soc-17__scrim {
display: none;
}
}@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600&display=swap');
.soc-17 {
--fg: #ffffff;
--muted: rgb(255 255 255 / .78);
--plate: rgb(255 255 255 / .12);
--edge: rgb(255 255 255 / .24);
--ring: #ffffff;
--sans: "Geist",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: #0c1013;
color: var(--fg);
font-family: var(--sans);
-webkit-font-smoothing: antialiased;
}
.soc-17[data-theme="light"] {
--plate: rgb(255 255 255 / .3);
--edge: rgb(255 255 255 / .5);
}
.soc-17,
.soc-17 *,
.soc-17 *::before,
.soc-17 *::after {
box-sizing: border-box;
}
.soc-17__stage {
position: relative;
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.25rem,5vw,3.5rem);
overflow: hidden;
}
.soc-17__bg {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
object-fit: cover;
background: #1a2228;
}
.soc-17__scrim {
position: absolute;
inset: 0;
background: linear-gradient(160deg,rgb(6 10 14 / .35),rgb(6 10 14 / .68));
}
.soc-17__glass {
position: relative;
inline-size: min(30rem,100%);
padding: clamp(1.5rem,4vw,2.25rem);
border-radius: 1.5rem;
border: 1px solid var(--edge);
background: var(--plate);
box-shadow: inset 0 1px 0 rgb(255 255 255 / .35), 0 30px 60px -30px rgb(0 0 0 / .8);
-webkit-backdrop-filter: blur(20px) saturate(170%);
backdrop-filter: blur(20px) saturate(170%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.soc-17__glass {
background: rgb(14 18 22 / .88);
}
.soc-17__btn {
background: rgb(255 255 255 / .16);
}
}
.soc-17__eyebrow {
margin: 0 0 .5rem;
font-size: .72rem;
font-weight: 600;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--muted);
}
.soc-17__title {
margin: 0 0 .3rem;
font-size: clamp(1.2rem,1rem + 1.1vw,1.6rem);
font-weight: 600;
letter-spacing: -.03em;
text-wrap: balance;
}
.soc-17__meta {
margin: 0 0 1.6rem;
font-size: .85rem;
color: var(--muted);
}
.soc-17__row {
display: flex;
flex-wrap: wrap;
gap: .6rem;
}
.soc-17__btn {
display: inline-flex;
align-items: center;
gap: .5rem;
min-block-size: 2.875rem;
padding: 0 1.1rem;
border-radius: .9rem;
border: 1px solid var(--edge);
background: rgb(255 255 255 / .1);
color: var(--fg);
text-decoration: none;
font-size: .9rem;
font-weight: 550;
min-inline-size: 0;
box-shadow: inset 0 1px 0 rgb(255 255 255 / .3);
-webkit-backdrop-filter: blur(10px) saturate(150%);
backdrop-filter: blur(10px) saturate(150%);
transition: background-color .22s ease, translate .22s cubic-bezier(.16,1,.3,1), border-color .22s ease;
}
.soc-17__btn--icon {
padding: 0;
inline-size: 2.875rem;
justify-content: center;
}
.soc-17__btn svg {
inline-size: 1.15rem;
block-size: 1.15rem;
}
.soc-17__btn:hover {
background: rgb(255 255 255 / .2);
translate: 0 -2px;
border-color: rgb(255 255 255 / .42);
}
.soc-17__btn:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.soc-17__btn {
transition-duration: 1ms;
}
.soc-17__btn:hover {
translate: none;
}
}
@media (forced-colors: active) {
.soc-17__glass,
.soc-17__btn {
background: Canvas;
color: CanvasText;
border: 1px solid CanvasText;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
.soc-17__scrim {
display: none;
}
}Here's a working CSS Social Button from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Glassmorphic Social Buttons over an Image
Source: https://codefronts.com/snippets/css-social-buttons/glassmorphic-social-buttons-over-an-image/
Frosted social buttons floating over a photograph: backdrop-filter blur with a saturation boost, a hairline inner highlight along the top edge, and a translucent border that reads as glass thickness. A @supports block declares a solid fallback first, so browsers without backdrop-filter get an opaque button instead of an unreadable one.
## HTML
```html
<div class="soc-17">
<div class="soc-17__stage">
<img class="soc-17__bg" src="https://images.unsplash.com/photo-1518495973542-4542c06a5843?w=1600&q=70&auto=format&fit=crop" alt="" width="1600" height="1000" loading="lazy" decoding="async">
<div class="soc-17__scrim" aria-hidden="true"></div>
<div class="soc-17__glass">
<p class="soc-17__eyebrow">Photograph series</p>
<h2 class="soc-17__title">Golden hour, Fitzroy Gardens</h2>
<p class="soc-17__meta">Print available · Sam Rivera</p>
<div class="soc-17__row">
<a class="soc-17__btn" style="--brand:#e1306c" href="https://example.com/samrivera" target="_blank" rel="noopener">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2"><rect x="3.6" y="3.6" width="16.8" height="16.8" rx="5"/><circle cx="12" cy="12" r="3.9"/><circle cx="17.1" cy="6.9" r="1.15" fill="currentColor" stroke="none"/></svg>
<span>Instagram</span>
</a>
<a class="soc-17__btn" style="--brand:#0f1419" href="https://example.com/samrivera" target="_blank" rel="noopener">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round"><path d="M5 5.5 19 18.5"/><path d="M19 5.5 5 18.5"/></svg>
<span>Post</span>
</a>
<a class="soc-17__btn soc-17__btn--icon" href="https://example.com/share" target="_blank" rel="noopener" aria-label="Share this photograph">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="17.5" cy="5.5" r="2.6"/><circle cx="6.5" cy="12" r="2.6"/><circle cx="17.5" cy="18.5" r="2.6"/><path d="m8.9 10.7 6.2-3.6"/><path d="m8.9 13.3 6.2 3.6"/></svg>
</a>
</div>
</div>
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600&display=swap');
.soc-17 {
--fg: #ffffff;
--muted: rgb(255 255 255 / .78);
--plate: rgb(255 255 255 / .12);
--edge: rgb(255 255 255 / .24);
--ring: #ffffff;
--sans: "Geist",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: #0c1013;
color: var(--fg);
font-family: var(--sans);
-webkit-font-smoothing: antialiased;
}
.soc-17[data-theme="light"] {
--plate: rgb(255 255 255 / .3);
--edge: rgb(255 255 255 / .5);
}
.soc-17,
.soc-17 *,
.soc-17 *::before,
.soc-17 *::after {
box-sizing: border-box;
}
.soc-17__stage {
position: relative;
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.25rem,5vw,3.5rem);
overflow: hidden;
}
.soc-17__bg {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
object-fit: cover;
background: #1a2228;
}
.soc-17__scrim {
position: absolute;
inset: 0;
background: linear-gradient(160deg,rgb(6 10 14 / .35),rgb(6 10 14 / .68));
}
.soc-17__glass {
position: relative;
inline-size: min(30rem,100%);
padding: clamp(1.5rem,4vw,2.25rem);
border-radius: 1.5rem;
border: 1px solid var(--edge);
background: var(--plate);
box-shadow: inset 0 1px 0 rgb(255 255 255 / .35), 0 30px 60px -30px rgb(0 0 0 / .8);
-webkit-backdrop-filter: blur(20px) saturate(170%);
backdrop-filter: blur(20px) saturate(170%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.soc-17__glass {
background: rgb(14 18 22 / .88);
}
.soc-17__btn {
background: rgb(255 255 255 / .16);
}
}
.soc-17__eyebrow {
margin: 0 0 .5rem;
font-size: .72rem;
font-weight: 600;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--muted);
}
.soc-17__title {
margin: 0 0 .3rem;
font-size: clamp(1.2rem,1rem + 1.1vw,1.6rem);
font-weight: 600;
letter-spacing: -.03em;
text-wrap: balance;
}
.soc-17__meta {
margin: 0 0 1.6rem;
font-size: .85rem;
color: var(--muted);
}
.soc-17__row {
display: flex;
flex-wrap: wrap;
gap: .6rem;
}
.soc-17__btn {
display: inline-flex;
align-items: center;
gap: .5rem;
min-block-size: 2.875rem;
padding: 0 1.1rem;
border-radius: .9rem;
border: 1px solid var(--edge);
background: rgb(255 255 255 / .1);
color: var(--fg);
text-decoration: none;
font-size: .9rem;
font-weight: 550;
min-inline-size: 0;
box-shadow: inset 0 1px 0 rgb(255 255 255 / .3);
-webkit-backdrop-filter: blur(10px) saturate(150%);
backdrop-filter: blur(10px) saturate(150%);
transition: background-color .22s ease, translate .22s cubic-bezier(.16,1,.3,1), border-color .22s ease;
}
.soc-17__btn--icon {
padding: 0;
inline-size: 2.875rem;
justify-content: center;
}
.soc-17__btn svg {
inline-size: 1.15rem;
block-size: 1.15rem;
}
.soc-17__btn:hover {
background: rgb(255 255 255 / .2);
translate: 0 -2px;
border-color: rgb(255 255 255 / .42);
}
.soc-17__btn:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.soc-17__btn {
transition-duration: 1ms;
}
.soc-17__btn:hover {
translate: none;
}
}
@media (forced-colors: active) {
.soc-17__glass,
.soc-17__btn {
background: Canvas;
color: CanvasText;
border: 1px solid CanvasText;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
.soc-17__scrim {
display: none;
}
}
```Here's a working CSS Social Button from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Glassmorphic Social Buttons over an Image
Source: https://codefronts.com/snippets/css-social-buttons/glassmorphic-social-buttons-over-an-image/
Frosted social buttons floating over a photograph: backdrop-filter blur with a saturation boost, a hairline inner highlight along the top edge, and a translucent border that reads as glass thickness. A @supports block declares a solid fallback first, so browsers without backdrop-filter get an opaque button instead of an unreadable one.
## HTML
```html
<div class="soc-17">
<div class="soc-17__stage">
<img class="soc-17__bg" src="https://images.unsplash.com/photo-1518495973542-4542c06a5843?w=1600&q=70&auto=format&fit=crop" alt="" width="1600" height="1000" loading="lazy" decoding="async">
<div class="soc-17__scrim" aria-hidden="true"></div>
<div class="soc-17__glass">
<p class="soc-17__eyebrow">Photograph series</p>
<h2 class="soc-17__title">Golden hour, Fitzroy Gardens</h2>
<p class="soc-17__meta">Print available · Sam Rivera</p>
<div class="soc-17__row">
<a class="soc-17__btn" style="--brand:#e1306c" href="https://example.com/samrivera" target="_blank" rel="noopener">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2"><rect x="3.6" y="3.6" width="16.8" height="16.8" rx="5"/><circle cx="12" cy="12" r="3.9"/><circle cx="17.1" cy="6.9" r="1.15" fill="currentColor" stroke="none"/></svg>
<span>Instagram</span>
</a>
<a class="soc-17__btn" style="--brand:#0f1419" href="https://example.com/samrivera" target="_blank" rel="noopener">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round"><path d="M5 5.5 19 18.5"/><path d="M19 5.5 5 18.5"/></svg>
<span>Post</span>
</a>
<a class="soc-17__btn soc-17__btn--icon" href="https://example.com/share" target="_blank" rel="noopener" aria-label="Share this photograph">
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="17.5" cy="5.5" r="2.6"/><circle cx="6.5" cy="12" r="2.6"/><circle cx="17.5" cy="18.5" r="2.6"/><path d="m8.9 10.7 6.2-3.6"/><path d="m8.9 13.3 6.2 3.6"/></svg>
</a>
</div>
</div>
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600&display=swap');
.soc-17 {
--fg: #ffffff;
--muted: rgb(255 255 255 / .78);
--plate: rgb(255 255 255 / .12);
--edge: rgb(255 255 255 / .24);
--ring: #ffffff;
--sans: "Geist",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: #0c1013;
color: var(--fg);
font-family: var(--sans);
-webkit-font-smoothing: antialiased;
}
.soc-17[data-theme="light"] {
--plate: rgb(255 255 255 / .3);
--edge: rgb(255 255 255 / .5);
}
.soc-17,
.soc-17 *,
.soc-17 *::before,
.soc-17 *::after {
box-sizing: border-box;
}
.soc-17__stage {
position: relative;
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.25rem,5vw,3.5rem);
overflow: hidden;
}
.soc-17__bg {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
object-fit: cover;
background: #1a2228;
}
.soc-17__scrim {
position: absolute;
inset: 0;
background: linear-gradient(160deg,rgb(6 10 14 / .35),rgb(6 10 14 / .68));
}
.soc-17__glass {
position: relative;
inline-size: min(30rem,100%);
padding: clamp(1.5rem,4vw,2.25rem);
border-radius: 1.5rem;
border: 1px solid var(--edge);
background: var(--plate);
box-shadow: inset 0 1px 0 rgb(255 255 255 / .35), 0 30px 60px -30px rgb(0 0 0 / .8);
-webkit-backdrop-filter: blur(20px) saturate(170%);
backdrop-filter: blur(20px) saturate(170%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.soc-17__glass {
background: rgb(14 18 22 / .88);
}
.soc-17__btn {
background: rgb(255 255 255 / .16);
}
}
.soc-17__eyebrow {
margin: 0 0 .5rem;
font-size: .72rem;
font-weight: 600;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--muted);
}
.soc-17__title {
margin: 0 0 .3rem;
font-size: clamp(1.2rem,1rem + 1.1vw,1.6rem);
font-weight: 600;
letter-spacing: -.03em;
text-wrap: balance;
}
.soc-17__meta {
margin: 0 0 1.6rem;
font-size: .85rem;
color: var(--muted);
}
.soc-17__row {
display: flex;
flex-wrap: wrap;
gap: .6rem;
}
.soc-17__btn {
display: inline-flex;
align-items: center;
gap: .5rem;
min-block-size: 2.875rem;
padding: 0 1.1rem;
border-radius: .9rem;
border: 1px solid var(--edge);
background: rgb(255 255 255 / .1);
color: var(--fg);
text-decoration: none;
font-size: .9rem;
font-weight: 550;
min-inline-size: 0;
box-shadow: inset 0 1px 0 rgb(255 255 255 / .3);
-webkit-backdrop-filter: blur(10px) saturate(150%);
backdrop-filter: blur(10px) saturate(150%);
transition: background-color .22s ease, translate .22s cubic-bezier(.16,1,.3,1), border-color .22s ease;
}
.soc-17__btn--icon {
padding: 0;
inline-size: 2.875rem;
justify-content: center;
}
.soc-17__btn svg {
inline-size: 1.15rem;
block-size: 1.15rem;
}
.soc-17__btn:hover {
background: rgb(255 255 255 / .2);
translate: 0 -2px;
border-color: rgb(255 255 255 / .42);
}
.soc-17__btn:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.soc-17__btn {
transition-duration: 1ms;
}
.soc-17__btn:hover {
translate: none;
}
}
@media (forced-colors: active) {
.soc-17__glass,
.soc-17__btn {
background: Canvas;
color: CanvasText;
border: 1px solid CanvasText;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
.soc-17__scrim {
display: none;
}
}
```How this works
Blur plus saturate is the whole recipe. Blur alone looks like fog; real frosted glass also intensifies the colour behind it. Saturation is what separates a convincing plate from a grey smear.
.soc-17__btn{
background:rgb(255 255 255 / .12);
backdrop-filter:blur(18px) saturate(180%);
border:1px solid rgb(255 255 255 / .22);
box-shadow:inset 0 1px 0 rgb(255 255 255 / .35);
}The inner highlight sells the thickness. A one-pixel inset shadow along the top edge mimics light catching the bevel. Without it the button reads as a flat translucent rectangle; with it, it reads as a physical pane sitting above the photograph.
Declare the fallback, do not hope. The @supports not (backdrop-filter: blur(1px)) block raises the background to a near-opaque colour. Skip it and users on unsupported engines get white text on a photograph at 12% opacity, which is unreadable rather than merely plain.
The trap: transformed and clipped ancestors. backdrop-filter samples the backdrop behind its element. An ancestor with overflow:hidden combined with a transform, filter or will-change creates a containing block that clips that backdrop, and the blur silently does nothing — the button just looks slightly transparent. If your glass stops working after adding a hover animation to a parent, this is why.
Make it yours
- Tune the frost with the blur radius; 10px is subtle glass, 28px is heavy diffusion.
- Raise the background alpha for more opacity over busy photographs.
- Swap the photograph for your own hero; keep the dark scrim so white labels stay legible.
- Change the border alpha to thicken or thin the perceived glass edge.
- Set
--brandper button to tint the hover state by channel. - Remove the scrim and increase the plate opacity instead if your image is already dark.
Gotchas — read before shipping
backdrop-filtersilently fails inside an ancestor that combinesoverflow:hiddenwith a transform or filter — the classic symptom is glass that works until someone animates a parent.- Without the
@supportsfallback, unsupported browsers render near-invisible buttons over the photograph. - Heavy blur over a large area is genuinely expensive on low-end GPUs; keep glass surfaces small and few.
- White text on glass over an unpredictable image can drop below 4.5:1 — a dark scrim between the image and the buttons is not optional.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 114+ | 17.5+ | 121+ | 114+ |
Floor set by backdrop-filter, text-wrap as this demo is written. The core technique itself goes back further — Chrome 76+.
backdrop-filter needs Chrome 76, Firefox 103 and Safari 18 unprefixed (Safari 9+ with the -webkit- prefix, which is included). Unsupported engines take the @supports fallback and get an opaque plate.