mixin icon(key)
-
const PATH_MAP = {
Twitter: "M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"
}
svg.button__icon(role='img' aria-hidden="true" xmlns='http://www.w3.org/2000/svg' viewbox='0 0 24 24')
title= `${key} Icon`
path(d=PATH_MAP[key])
.scene
button.button
span.button__shadow
+icon('Twitter')
span.button__content
span.button__text Twitter
+icon('Twitter')
span.button__shine
View Compiled
*
box-sizing border-box
transform-style preserve-3d
:root
--blur 8px
--shine-blur calc(var(--blur) * 4)
--size 25vmin
--transition 0.1s
--depth max(25px, 3vmin)
--icon-size 75%
--radius 24%
--shine hsla(0, 0%, 100%, 0.85)
--button-bg hsla(0, 0%, 0%, 0.025)
--icon-fill hsl(206, 82%, 63%)
--shadow-fill hsla(0, 0%, 0%, 0.4)
--shadow-bg hsla(0, 0%, 0%, 0.1)
--shadow-icon hsla(0, 0%, 0%, 0.35)
--bg hsl(206, 82%, 95%)
body
min-height 100vh
display grid
place-items center
transform-style preserve-3d
touch-action none
overflow hidden
&:before
content ''
position absolute
height 300vh
width 300vw
z-index -1
top 50%
left 50%
transform translate3d(-50%, -50%, calc(var(--size) * -1))
background var(--bg)
.scene
height var(--size)
position relative
min-height 150px
min-width 150px
width var(--size)
transform rotateX(-40deg) rotateY(18deg) rotateX(90deg)
.button
appearance none
background none
border 0
cursor pointer
height 100%
outline transparent
position absolute
width 100%
&__content
&__shadow
height 100%
width 100%
position absolute
display grid
place-items center
border-radius var(--radius)
&__content
--fill var(--icon-fill)
background var(--button-bg)
overflow visible
backdrop-filter blur(calc(var(--blur) * 0.25))
transform translate3d(0, 0, var(--depth))
transition transform var(--transition), backdrop-filter var(--transition)
&__shadow
--fill var(--shadow-fill)
background var(--shadow-bg)
filter blur(var(--blur))
transition filter var(--transition)
&__text
position absolute
width 1px
height 1px
padding 0
margin -1px
overflow hidden
clip rect(0, 0, 0, 0)
white-space nowrap
border-width 0
&__shine
--shine-size calc(var(--size) * 0.5)
background red
border-radius 50%
height var(--shine-size)
min-height 75px
min-width 75px
position absolute
left 0
top 0
transform translate3d(-50%, -50%, 1vmin) translate(calc(var(--x) * 1%), calc(var(--y) * 1%))
width var(--shine-size)
&__icon
height var(--icon-size)
fill var(--fill)
width var(--icon-size)
&:active
--depth 0
--blur 0
View Compiled
import gsap from 'https://cdn.skypack.dev/gsap'
const BUTTON = document.querySelector('.button')
const CONTENT = document.querySelector('.button__content')
const SHINE = document.querySelector('.button__shine')
const UPDATE = ({x, y}) => {
const BOUNDS = CONTENT.getBoundingClientRect()
const POS_X = ((x - BOUNDS.x) / BOUNDS.width) * 200
const POS_Y = ((y - BOUNDS.y) / BOUNDS.height) * 200
gsap.set(SHINE, {
'--x': POS_X,
'--y': POS_Y
})
}
document.addEventListener('pointermove', UPDATE)
document.addEventListener('pointerdown', UPDATE)
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.