HER Button

by Chris Ball

HTML

<link href="https://fonts.cdnfonts.com/css/lexend-deca" rel="stylesheet" />
<style>@import url('https://fonts.cdnfonts.com/css/lexend-deca');</style>
<div id="cursor"></div>

<button class="small">Buy Tickets</button>
<button>Buy Tickets</button>
<button class="large">Buy Tickets</button>

CSS

:root {
  --her-purple: #4E3366;
  --her-pink: #FFCCD0;
}

html, body {
  height: 100%;
}

#cursor {
  background: var(--her-pink);
  border-radius: 50%;
  height: 1em;
  left:0;
  pointer-events: none!important;
  position: fixed;
  top:0;
  transition: transform 80ms, opacity 600ms;
  width: 1em;
  z-index: 20000;
}

@property --button_blur-start-color{
  syntax: "<color>";
  inherits: true;
  initial-value: transparent;
}

button {
  --button_blur-start: 0.5em;
  --button_blur-end: 3.5em;
  --button_hover-bg-color: hsl(from var(--her-pink) h s calc(l + 6));
  /* --button_hover-bg-color: transparent; */
  --x-pos: 0;
  --y-pos: 0;

  background-color: transparent;
  background-image: radial-gradient(
    circle at var(--x-pos) var(--y-pos),
    var(--button_blur-start-color) var(--button_blur-start),
    transparent var(--button_blur-end)
  );
  border: none;
  border-radius: 100vmax;
  color: var(--her-purple);
  font-family: 'Lexend Deca', sans-serif;
  font-size: inherit;
  font-feature-settings: "ss01" 1;
  font-variation-settings: "wght" 550;
  overflow: hidden;
  padding: 0.5em 0.75em;
  transition: background-color 600ms, --button_blur-start-color 300ms;

  /* Size variants */
  &.large { font-size: 21px }
  &.small { font-size: 13px }

  &:hover {
    --button_blur-start-color: var(--her-pink);
    background-color: var(--button_hover-bg-color);
  }
}

JavaScript

/****************************************
 * Button Shit
 ****************************************/
let buttons = document.querySelectorAll('button');
let output = document.querySelector('#output');

[...buttons].forEach((button) => {
  button.addEventListener('mousemove', ({offsetX, offsetY}) => {
    requestAnimationFrame(() => {
      button.style = `--x-pos:${offsetX}px; --y-pos:${offsetY}px;`;
    })
  })
})

/****************************************
 * Cursor Shit
 ****************************************/

class Cursory {
  defaults = {
    elSelector: '#cursor',
    delay: 0.2,
    hideOn: ['button']
  }

  target = null
  currentX = 0
  currentY = 0
  targetX = 0
  targetY = 0

  constructor(config) {
    this.settings = {...this.defaults, ...config}
    this.el = document.querySelector(this.settings.elSelector)
    this.addHandlers()
  }

  go() {
    requestAnimationFrame(() => this.updateFollower())
  }

  addHandlers() {
    document.body.addEventListener('mousemove', (e) => {
      this.targetX = e.clientX
      this.targetY = e.clientY
    })
  }

  updateFollower(e) {
    this.currentX += (this.targetX - this.currentX) * this.settings.delay
    this.currentY += (this.targetY - this.currentY) * this.settings.delay

    for (const selector of this.settings.hideOn) {
      requestAnimationFrame(() => {
        this.el.style.transform = `translate3d(calc(${this.currentX}px - 50%), calc(${this.currentY}px - 50%), 0)`
      })

      if (this.target.matches(selector)) {
        this.hide()
        break;
      } else {
        this.show()
      }
    }

    requestAnimationFrame(this.updateFollower)
  }

  show() {
    this.el.style.opacity = 1
  }
  hide() {
    this.el.style.opacity = 0
  }
}

let cursory = new Cursory({ hideOn: ['button'] })
cursory.go()

// let cursorDiv = document.querySelector('#cursor')
// let hiddenCursorSelectors = ['button']

// function...