51 CSS Buttons34 / 51
CSS Obsidian Glass Shard Button
A shard of volcanic glass: an asymmetric faceted silhouette from clip-path, near-black translucency over a blurred backdrop, two facet planes shaded by overlapping gradients, and a razor of light that runs along the leading edge on hover.
Published Updated
The code
<div class="cb-34">
<div class="cb-34__stage">
<span class="cb-34__wrap">
<button class="cb-34__btn" type="button">
<span class="cb-34__rim" aria-hidden="true"></span>
<span class="cb-34__edge" aria-hidden="true"></span>
<span class="cb-34__label">Enter the vault</span>
</button>
</span>
</div>
</div><div class="cb-34">
<div class="cb-34__stage">
<span class="cb-34__wrap">
<button class="cb-34__btn" type="button">
<span class="cb-34__rim" aria-hidden="true"></span>
<span class="cb-34__edge" aria-hidden="true"></span>
<span class="cb-34__label">Enter the vault</span>
</button>
</span>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&display=swap');
.cb-34 {
--bg: #07070a;
--glass: rgba(16,17,22,.82);
--ink: #eef2f8;
--glow: #bfe3ff;
--shape: polygon(4% 0,100% 6%,96% 82%,88% 100%,0 94%,3% 18%);
--sans: "Syne",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: radial-gradient(38rem 22rem at 50% 45%, #14161d, transparent 74%), var(--bg);
font-family: var(--sans);
-webkit-font-smoothing: antialiased;
}
@media (prefers-color-scheme: light) {
.cb-34:not([data-theme="dark"]) {
--bg: #101218;
}
}
.cb-34[data-theme="light"] {
--bg: #101218;
}
.cb-34,
.cb-34 *,
.cb-34 *::before,
.cb-34 *::after {
box-sizing: border-box;
}
.cb-34__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.5rem,6vw,4rem);
}
.cb-34__wrap {
display: inline-block;
border-radius: .2rem;
filter: drop-shadow(0 18px 28px rgba(0,0,0,.75)) drop-shadow(0 0 1px rgba(190,225,255,.25));
transition: translate .35s cubic-bezier(.16,1,.3,1), filter .35s ease;
}
.cb-34__wrap:has(:hover) {
translate: 0 -3px;
filter: drop-shadow(0 26px 34px rgba(0,0,0,.8)) drop-shadow(0 0 2px rgba(190,225,255,.45));
}
.cb-34__wrap:has(:focus-visible) {
outline: 2px solid var(--glow);
outline-offset: 6px;
}
.cb-34__btn {
position: relative;
overflow: hidden;
cursor: pointer;
display: grid;
place-items: center;
min-height: 3.75rem;
padding: 0 3rem;
border: 0;
clip-path: var(--shape);
font: inherit;
font-size: 1rem;
font-weight: 700;
letter-spacing: .02em;
color: var(--ink);
background-image: linear-gradient(122deg, rgba(255,255,255,.1) 0 38%, transparent 38.5%), linear-gradient(-58deg, rgba(255,255,255,.05) 0 30%, transparent 30.5%), linear-gradient(160deg, rgba(52,58,74,.95), rgba(14,16,22,.97));
background-color: var(--glass);
-webkit-backdrop-filter: blur(10px) saturate(1.2);
backdrop-filter: blur(10px) saturate(1.2);
transition: scale .2s cubic-bezier(.16,1,.3,1);
}
.cb-34__label {
position: relative;
z-index: 3;
text-shadow: 0 1px 10px rgba(0,0,0,.7);
}
.cb-34__rim {
position: absolute;
inset: 1px;
z-index: 1;
pointer-events: none;
clip-path: var(--shape);
box-shadow: inset 0 0 0 1px rgba(190,225,255,.3);
}
.cb-34__edge {
position: absolute;
inset: -30% -40%;
z-index: 2;
pointer-events: none;
background: linear-gradient(100deg, transparent 44%, rgba(190,225,255,.85) 50%, transparent 56%);
translate: -70% 0;
transition: translate .85s cubic-bezier(.16,1,.3,1);
}
.cb-34__btn:is(:hover,:focus-visible) .cb-34__edge {
translate: 70% 0;
}
.cb-34__btn:focus-visible {
outline: none;
}
.cb-34__btn:active {
scale: .985;
}
.cb-34__btn:disabled {
cursor: not-allowed;
color: #7c8494;
}
@media (prefers-reduced-motion: reduce) {
.cb-34__wrap,
.cb-34__btn,
.cb-34__edge {
transition: none;
}
}
@media (forced-colors: active) {
.cb-34__btn {
clip-path: none;
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
.cb-34__rim,
.cb-34__edge {
display: none;
}
.cb-34__wrap {
filter: none;
}
}@import url('https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&display=swap');
.cb-34 {
--bg: #07070a;
--glass: rgba(16,17,22,.82);
--ink: #eef2f8;
--glow: #bfe3ff;
--shape: polygon(4% 0,100% 6%,96% 82%,88% 100%,0 94%,3% 18%);
--sans: "Syne",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: radial-gradient(38rem 22rem at 50% 45%, #14161d, transparent 74%), var(--bg);
font-family: var(--sans);
-webkit-font-smoothing: antialiased;
}
@media (prefers-color-scheme: light) {
.cb-34:not([data-theme="dark"]) {
--bg: #101218;
}
}
.cb-34[data-theme="light"] {
--bg: #101218;
}
.cb-34,
.cb-34 *,
.cb-34 *::before,
.cb-34 *::after {
box-sizing: border-box;
}
.cb-34__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.5rem,6vw,4rem);
}
.cb-34__wrap {
display: inline-block;
border-radius: .2rem;
filter: drop-shadow(0 18px 28px rgba(0,0,0,.75)) drop-shadow(0 0 1px rgba(190,225,255,.25));
transition: translate .35s cubic-bezier(.16,1,.3,1), filter .35s ease;
}
.cb-34__wrap:has(:hover) {
translate: 0 -3px;
filter: drop-shadow(0 26px 34px rgba(0,0,0,.8)) drop-shadow(0 0 2px rgba(190,225,255,.45));
}
.cb-34__wrap:has(:focus-visible) {
outline: 2px solid var(--glow);
outline-offset: 6px;
}
.cb-34__btn {
position: relative;
overflow: hidden;
cursor: pointer;
display: grid;
place-items: center;
min-height: 3.75rem;
padding: 0 3rem;
border: 0;
clip-path: var(--shape);
font: inherit;
font-size: 1rem;
font-weight: 700;
letter-spacing: .02em;
color: var(--ink);
background-image: linear-gradient(122deg, rgba(255,255,255,.1) 0 38%, transparent 38.5%), linear-gradient(-58deg, rgba(255,255,255,.05) 0 30%, transparent 30.5%), linear-gradient(160deg, rgba(52,58,74,.95), rgba(14,16,22,.97));
background-color: var(--glass);
-webkit-backdrop-filter: blur(10px) saturate(1.2);
backdrop-filter: blur(10px) saturate(1.2);
transition: scale .2s cubic-bezier(.16,1,.3,1);
}
.cb-34__label {
position: relative;
z-index: 3;
text-shadow: 0 1px 10px rgba(0,0,0,.7);
}
.cb-34__rim {
position: absolute;
inset: 1px;
z-index: 1;
pointer-events: none;
clip-path: var(--shape);
box-shadow: inset 0 0 0 1px rgba(190,225,255,.3);
}
.cb-34__edge {
position: absolute;
inset: -30% -40%;
z-index: 2;
pointer-events: none;
background: linear-gradient(100deg, transparent 44%, rgba(190,225,255,.85) 50%, transparent 56%);
translate: -70% 0;
transition: translate .85s cubic-bezier(.16,1,.3,1);
}
.cb-34__btn:is(:hover,:focus-visible) .cb-34__edge {
translate: 70% 0;
}
.cb-34__btn:focus-visible {
outline: none;
}
.cb-34__btn:active {
scale: .985;
}
.cb-34__btn:disabled {
cursor: not-allowed;
color: #7c8494;
}
@media (prefers-reduced-motion: reduce) {
.cb-34__wrap,
.cb-34__btn,
.cb-34__edge {
transition: none;
}
}
@media (forced-colors: active) {
.cb-34__btn {
clip-path: none;
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
.cb-34__rim,
.cb-34__edge {
display: none;
}
.cb-34__wrap {
filter: none;
}
}Here's a working CSS 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: CSS Obsidian Glass Shard Button
Source: https://codefronts.com/components/css-buttons/css-obsidian-glass-shard-button/
A shard of volcanic glass: an asymmetric faceted silhouette from clip-path, near-black translucency over a blurred backdrop, two facet planes shaded by overlapping gradients, and a razor of light that runs along the leading edge on hover.
## HTML
```html
<div class="cb-34">
<div class="cb-34__stage">
<span class="cb-34__wrap">
<button class="cb-34__btn" type="button">
<span class="cb-34__rim" aria-hidden="true"></span>
<span class="cb-34__edge" aria-hidden="true"></span>
<span class="cb-34__label">Enter the vault</span>
</button>
</span>
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&display=swap');
.cb-34 {
--bg: #07070a;
--glass: rgba(16,17,22,.82);
--ink: #eef2f8;
--glow: #bfe3ff;
--shape: polygon(4% 0,100% 6%,96% 82%,88% 100%,0 94%,3% 18%);
--sans: "Syne",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: radial-gradient(38rem 22rem at 50% 45%, #14161d, transparent 74%), var(--bg);
font-family: var(--sans);
-webkit-font-smoothing: antialiased;
}
@media (prefers-color-scheme: light) {
.cb-34:not([data-theme="dark"]) {
--bg: #101218;
}
}
.cb-34[data-theme="light"] {
--bg: #101218;
}
.cb-34,
.cb-34 *,
.cb-34 *::before,
.cb-34 *::after {
box-sizing: border-box;
}
.cb-34__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.5rem,6vw,4rem);
}
.cb-34__wrap {
display: inline-block;
border-radius: .2rem;
filter: drop-shadow(0 18px 28px rgba(0,0,0,.75)) drop-shadow(0 0 1px rgba(190,225,255,.25));
transition: translate .35s cubic-bezier(.16,1,.3,1), filter .35s ease;
}
.cb-34__wrap:has(:hover) {
translate: 0 -3px;
filter: drop-shadow(0 26px 34px rgba(0,0,0,.8)) drop-shadow(0 0 2px rgba(190,225,255,.45));
}
.cb-34__wrap:has(:focus-visible) {
outline: 2px solid var(--glow);
outline-offset: 6px;
}
.cb-34__btn {
position: relative;
overflow: hidden;
cursor: pointer;
display: grid;
place-items: center;
min-height: 3.75rem;
padding: 0 3rem;
border: 0;
clip-path: var(--shape);
font: inherit;
font-size: 1rem;
font-weight: 700;
letter-spacing: .02em;
color: var(--ink);
background-image: linear-gradient(122deg, rgba(255,255,255,.1) 0 38%, transparent 38.5%), linear-gradient(-58deg, rgba(255,255,255,.05) 0 30%, transparent 30.5%), linear-gradient(160deg, rgba(52,58,74,.95), rgba(14,16,22,.97));
background-color: var(--glass);
-webkit-backdrop-filter: blur(10px) saturate(1.2);
backdrop-filter: blur(10px) saturate(1.2);
transition: scale .2s cubic-bezier(.16,1,.3,1);
}
.cb-34__label {
position: relative;
z-index: 3;
text-shadow: 0 1px 10px rgba(0,0,0,.7);
}
.cb-34__rim {
position: absolute;
inset: 1px;
z-index: 1;
pointer-events: none;
clip-path: var(--shape);
box-shadow: inset 0 0 0 1px rgba(190,225,255,.3);
}
.cb-34__edge {
position: absolute;
inset: -30% -40%;
z-index: 2;
pointer-events: none;
background: linear-gradient(100deg, transparent 44%, rgba(190,225,255,.85) 50%, transparent 56%);
translate: -70% 0;
transition: translate .85s cubic-bezier(.16,1,.3,1);
}
.cb-34__btn:is(:hover,:focus-visible) .cb-34__edge {
translate: 70% 0;
}
.cb-34__btn:focus-visible {
outline: none;
}
.cb-34__btn:active {
scale: .985;
}
.cb-34__btn:disabled {
cursor: not-allowed;
color: #7c8494;
}
@media (prefers-reduced-motion: reduce) {
.cb-34__wrap,
.cb-34__btn,
.cb-34__edge {
transition: none;
}
}
@media (forced-colors: active) {
.cb-34__btn {
clip-path: none;
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
.cb-34__rim,
.cb-34__edge {
display: none;
}
.cb-34__wrap {
filter: none;
}
}
```Here's a working CSS 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: CSS Obsidian Glass Shard Button
Source: https://codefronts.com/components/css-buttons/css-obsidian-glass-shard-button/
A shard of volcanic glass: an asymmetric faceted silhouette from clip-path, near-black translucency over a blurred backdrop, two facet planes shaded by overlapping gradients, and a razor of light that runs along the leading edge on hover.
## HTML
```html
<div class="cb-34">
<div class="cb-34__stage">
<span class="cb-34__wrap">
<button class="cb-34__btn" type="button">
<span class="cb-34__rim" aria-hidden="true"></span>
<span class="cb-34__edge" aria-hidden="true"></span>
<span class="cb-34__label">Enter the vault</span>
</button>
</span>
</div>
</div>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&display=swap');
.cb-34 {
--bg: #07070a;
--glass: rgba(16,17,22,.82);
--ink: #eef2f8;
--glow: #bfe3ff;
--shape: polygon(4% 0,100% 6%,96% 82%,88% 100%,0 94%,3% 18%);
--sans: "Syne",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: radial-gradient(38rem 22rem at 50% 45%, #14161d, transparent 74%), var(--bg);
font-family: var(--sans);
-webkit-font-smoothing: antialiased;
}
@media (prefers-color-scheme: light) {
.cb-34:not([data-theme="dark"]) {
--bg: #101218;
}
}
.cb-34[data-theme="light"] {
--bg: #101218;
}
.cb-34,
.cb-34 *,
.cb-34 *::before,
.cb-34 *::after {
box-sizing: border-box;
}
.cb-34__stage {
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(1.5rem,6vw,4rem);
}
.cb-34__wrap {
display: inline-block;
border-radius: .2rem;
filter: drop-shadow(0 18px 28px rgba(0,0,0,.75)) drop-shadow(0 0 1px rgba(190,225,255,.25));
transition: translate .35s cubic-bezier(.16,1,.3,1), filter .35s ease;
}
.cb-34__wrap:has(:hover) {
translate: 0 -3px;
filter: drop-shadow(0 26px 34px rgba(0,0,0,.8)) drop-shadow(0 0 2px rgba(190,225,255,.45));
}
.cb-34__wrap:has(:focus-visible) {
outline: 2px solid var(--glow);
outline-offset: 6px;
}
.cb-34__btn {
position: relative;
overflow: hidden;
cursor: pointer;
display: grid;
place-items: center;
min-height: 3.75rem;
padding: 0 3rem;
border: 0;
clip-path: var(--shape);
font: inherit;
font-size: 1rem;
font-weight: 700;
letter-spacing: .02em;
color: var(--ink);
background-image: linear-gradient(122deg, rgba(255,255,255,.1) 0 38%, transparent 38.5%), linear-gradient(-58deg, rgba(255,255,255,.05) 0 30%, transparent 30.5%), linear-gradient(160deg, rgba(52,58,74,.95), rgba(14,16,22,.97));
background-color: var(--glass);
-webkit-backdrop-filter: blur(10px) saturate(1.2);
backdrop-filter: blur(10px) saturate(1.2);
transition: scale .2s cubic-bezier(.16,1,.3,1);
}
.cb-34__label {
position: relative;
z-index: 3;
text-shadow: 0 1px 10px rgba(0,0,0,.7);
}
.cb-34__rim {
position: absolute;
inset: 1px;
z-index: 1;
pointer-events: none;
clip-path: var(--shape);
box-shadow: inset 0 0 0 1px rgba(190,225,255,.3);
}
.cb-34__edge {
position: absolute;
inset: -30% -40%;
z-index: 2;
pointer-events: none;
background: linear-gradient(100deg, transparent 44%, rgba(190,225,255,.85) 50%, transparent 56%);
translate: -70% 0;
transition: translate .85s cubic-bezier(.16,1,.3,1);
}
.cb-34__btn:is(:hover,:focus-visible) .cb-34__edge {
translate: 70% 0;
}
.cb-34__btn:focus-visible {
outline: none;
}
.cb-34__btn:active {
scale: .985;
}
.cb-34__btn:disabled {
cursor: not-allowed;
color: #7c8494;
}
@media (prefers-reduced-motion: reduce) {
.cb-34__wrap,
.cb-34__btn,
.cb-34__edge {
transition: none;
}
}
@media (forced-colors: active) {
.cb-34__btn {
clip-path: none;
background: ButtonFace;
color: ButtonText;
border: 1px solid ButtonText;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
.cb-34__rim,
.cb-34__edge {
display: none;
}
.cb-34__wrap {
filter: none;
}
}
```How this works
The silhouette is a six-point polygon with deliberately unequal chamfers, so no two corners match — symmetry would read as a coupon, not a shard:
clip-path:polygon(4% 0,100% 6%,96% 82%,88% 100%,0 94%,3% 18%);Because clip-path discards box-shadow, the drop shadow has to come from a filter on a wrapper. The facets are two large linear gradients at opposing angles with hard-ish midpoints, which is what makes flat planes rather than a smooth sheen. The edge light is a thin, rotated gradient bar clipped by the same shape and translated across on hover:
.cb-34__edge{
background:linear-gradient(100deg, transparent 44%, rgba(190,225,255,.9) 50%, transparent 56%);
translate:-70% 0; transition:translate .8s cubic-bezier(.16,1,.3,1);
}
.cb-34__btn:is(:hover,:focus-visible) .cb-34__edge{ translate:70% 0; }A 1px inner rim is faked with a second clipped layer inset by 1px in a lighter colour — clipped shapes cannot take a border, so this is the standard workaround.
Make it yours
- Redraw the facets by editing the polygon; keep at least one long straight edge so the label has room.
- Change
--glowfor the edge light — icy blue reads as obsidian, amber as smoked quartz. - Add a second edge sweep at a different angle with a delay for a multi-facet catch.
- Raise the backdrop blur for frosted volcanic glass, or drop it for opaque stone.
Gotchas — read before shipping
clip-pathkillsbox-shadowandborder. Use a wrapper withfilter:drop-shadow()and a clipped inner layer for the rim.- Angular shapes shrink the effective hit area at the corners; keep the label well inside and the height ≥ 3rem.
- Focus rings follow the border box, not the clip. An
outlineon a clipped element looks wrong — put it on the wrapper (as here). - Sharp geometric buttons read as decorative; the label must be an unambiguous verb or users won't recognise it as a control.
- Very dark surfaces need a light label at ≥ 4.5:1 — near-black on near-black is a common failure in this style.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 105+ | 15.4+ | 121+ | 105+ |
Floor set by :has(), backdrop-filter as this demo is written. The core technique itself goes back further — Chrome 88+.
clip-path polygon and filter:drop-shadow are baseline. backdrop-filter needs Chrome 76 / Safari 9 (prefixed) / Firefox 103 and degrades to the solid translucent background declared first.