Created
April 19, 2024 02:12
-
-
Save disco0/e70595a7ca0ff4a7d70b65a6d76227d0 to your computer and use it in GitHub Desktop.
Glass buttons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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`); | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
: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