Skip to content

Instantly share code, notes, and snippets.

@disco0
Created April 19, 2024 02:12
Show Gist options
  • Save disco0/e70595a7ca0ff4a7d70b65a6d76227d0 to your computer and use it in GitHub Desktop.
Save disco0/e70595a7ca0ff4a7d70b65a6d76227d0 to your computer and use it in GitHub Desktop.
Glass buttons
<button class="glassy-button"><span>Get started</span></button>
<button class="glassy-button"><span>Get started</span></button>
<div class="meta">
<p>Inspired by <a href="https://dribbble.com/shots/22117329-Glass-Buttons">this Dribbble shot</a> by Patrick Hill</p>
<p>I have <a href="https://youtu.be/XJt2_NNnRms">a full tutorial</a> on making it, as well 😊</p>
</div>
const glassyButtons = document.querySelectorAll(".glassy-button");
glassyButtons.forEach((button) => {
button.addEventListener("mousemove", (event) => {
const centerX = button.offsetWidth / 2;
const centerY = button.offsetHeight / 2;
const offsetX = event.offsetX - centerX;
const offsetY = event.offsetY - centerY;
button.style.setProperty("--_x-motion", `${offsetX}px`);
button.style.setProperty("--_y-motion", `${offsetY}px`);
});
});
:root {
--bg: hsl(221, 37%, 10%);
--button-text: hsl(200, 60%, 12%);
--button-1-surface: hsl(197, 88%, 58%);
--button-2-surface: hsl(41, 96%, 56%);
}
html {
color-scheme: dark;
font-family: system-ui;
font-size: 2rem;
background: var(--bg);
}
body {
min-height: 80vh;
display: flex;
gap: 1rem;
justify-content: center;
place-items: center;
}
.glassy-button {
--_padding: 1rem 1.5rem;
--_transition-speed: 200ms;
--_hover-opacity: 0.4;
--_pressed-opacity: 0.15;
--_hover-blurriness: 5px;
--_pressed-blurriness: 10px;
--_frostiness: 0.3;
--_hover-offset: 0.5rem;
--_pressed-offset: 0.25rem;
--_motion-factor: 0.1; /* 0 -> 1 */
outline: 0;
cursor: pointer;
font: inherit;
color: var(--button-text);
font-weight: 500;
padding: 0;
border: 0;
border-radius: 1rem;
background-color: transparent;
position: relative;
span {
display: block;
overflow: hidden;
padding: var(--_padding);
border-radius: inherit;
background-color: hsl(0 0% 100% / 0);
backdrop-filter: blur(0px);
transition: background-color var(--_transition-speed),
backdrop-filter var(--_transition-speed),
translate var(--_transition-speed);
&::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
background-image: url("data:image/svg+xml, %3C!-- svg: first layer --%3E%3Csvg viewBox='0 0 171 171' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='3.74' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
opacity: 0;
transition: opacity var(--_transition-speed);
}
}
&::after {
content: "";
position: absolute;
z-index: -1;
inset: 0;
border-radius: inherit;
background-color: var(--_surface);
transition: scale var(--_transition-speed),
translate var(--_transition-speed);
animation: exit forwards var(--_transition-speed);
}
&:hover,
&:focus-visible {
span {
outline: 1px solid hsl(0 0% 100% / 0.7);
background-color: hsl(0 0% 100% / var(--_hover-opacity));
backdrop-filter: blur(var(--_hover-blurriness));
translate: 0 calc(var(--_hover-offset) * -1);
&::before {
opacity: var(--_frostiness);
}
}
&::after {
scale: 0.95;
translate: 0 0.125rem;
animation: enter forwards var(--_transition-speed);
}
}
&:active {
span {
backdrop-filter: blur(var(--_pressed-blurriness));
background-color: hsl(0 0% 100% / var(--_pressed-opacity));
translate: 0 calc(var(--_pressed-offset) * -1);
}
&::after {
scale: 0.875;
translate: 0 0.25rem;
}
}
}
@keyframes enter {
from {
transform: translate(0, 0);
}
to {
transform: translate(
calc(var(--_x-motion) * var(--_motion-factor) * -1),
calc(var(--_y-motion) * var(--_motion-factor) * -1)
);
}
}
@keyframes exit {
from {
transform: translate(
calc(var(--_x-motion) * var(--_motion-factor) * -1),
calc(var(--_y-motion) * var(--_motion-factor) * -1)
);
}
to {
transform: translate(0, 0);
}
}
.glassy-button:nth-child(1) {
--_surface: var(--button-1-surface);
}
.glassy-button:nth-child(2) {
--_surface: var(--button-2-surface);
}
@layer not-demo-related {
.meta {
font-size: 0.625rem;
text-align: center;
position: fixed;
inset: auto 2rem 2rem;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment