<div class="cbtn-wrap">
  <div id="cbtn-title"></div>
  <div class="cbtn-nav" id="nav-prev">
    <i class="fas fa-chevron-left"></i>
  </div>
  <div class="cbtn-o" id="cbtn1">
    <div class="cbtn-i" data-mode="0">Hover / Click / Hold</div>
  </div>
  <div class="cbtn-nav" id="nav-next">
    <i class="fas fa-chevron-right"></i>
  </div>

  <div class="info-wrap">
    <div class="info-text"></div>
  </div>
</div>

<div class="social">
  <a class="icon" href="https://twitter.com/Tiibiix" target="_blank">
    <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/1692350/twitter-icon-256.png"/>
  </a>
</div>
@import url('https://fonts.googleapis.com/css?family=Montserrat&display=swap');

html,body{
  margin: 0px;
  background: #000;
}

.cbtn-wrap{
  overflow: hidden;
  text-align: center;
  margin-top: 50px;
}

#cbtn-title{
  position: relative;
  font-family: Montserrat;
  color: #fff;
  font-size: 24px;
  text-transform: uppercase;
  font-weight: 600;
  text-decoration: underline;
}

.cbtn-o{
  display: inline-block;
  position: relative;

  & > .cbtn-i{
    position: relative;
    z-index: 3;
    cursor: pointer;
    margin: 40px 20px;
    padding: 10px 25px;
    border-radius: 100px;
    font-family: Montserrat;
    font-weight: 600;
    color: #fff;
    text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
    transition: 250ms cubic-bezier(0,.5,.5,1);
    -webkit-touch-callout: none;
    -webkit-user-select: none;
     -khtml-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;
    
    &[data-mode="0"]{
      background: #e96651;
      box-shadow: 0px 0px 0px #e96651;
      
      &:hover{
        transform: scale(0.9);
        background: #efaf60;
        box-shadow: 0px 0px 30px #efaf60;
      }
      
      &:active{
        transform: scale(1);
      }
    }
    
    &[data-mode="1"]{
      background: #3770a0;
      box-shadow: 0px 0px 0px #3770a0;
      
      &:hover{
        transform: scale(0.9);
        background: #77b6ea;
        box-shadow: 0px 0px 20px #77b6ea;
      }
      
      &:active{
        transform: scale(0.6);
      }
    }
    
    &[data-mode="2"]{
      background: #30a254;
      box-shadow: 0px 0px 0px #30a254;
      transition: 350ms cubic-bezier(0,.5,.5,1);
      
      &:hover{
        transform: scale(0.9);
        background: #51e980;
        box-shadow: 0px 0px 30px #51e980;
      }
      
      &:active{
        transform: scale(0.9) rotateX(-360deg);
      }
    }
    
    &[data-mode="3"]{
      background: #8e54ff;
      box-shadow: 0px 0px 0px #8e54ff;
      
      &:hover{
        transform: scale(0.9);
        background: #a93ee0;
        box-shadow: 0px 0px 30px #a93ee0;
      }
      
      &:active{
        transform: scale(0.9) rotate(-360deg);
      }
    }
    
    &[data-mode="4"]{
      background: #ff0000;
      box-shadow: 0px 0px 0px #ff0000;
      
      &:hover{
        transform: scale(0.9);
        background: #ff0000;
        box-shadow: 0px 0px 30px #ff0000;
      }
      
      &:active{
        transition: none;
        filter: blur(7px);
        color: transparent;
      }
    }
  }

  & > canvas{
    position: absolute;
    z-index: 2;
    top: 0px;
    left: 0px;
  }
}

.cbtn-nav{
  color: #fff;
  display: inline-block;
  position: relative;
  z-index: 1;
  font-size: 18px;
  padding: 10px;
  cursor: pointer;
  text-shadow: 2px 2px 4px #111;

  &#nav-next{
    margin-left: 20px;
    &::before{
      left: 15px;
    }
  }

  &#nav-prev{
    margin-right: 20px;
    &::before{
      left: 17px;
    }
  }

  &:hover::before{
    width: 40px;
    height: 40px;
  }
  
  &::before{
    content: "";
    position: absolute;
    border-radius: 100px;
    top: 20px;
    transform: translate(-50%, -50%);
    height: 0px;
    width: 0px;
    background: #333333;
    z-index: -1;
    transition: 150ms ease-in-out;
  }
}

.next_anim{
  animation: next 600ms ease;
  pointer-events: none;
}

.prev_anim{
  animation: prev 600ms ease;
  pointer-events: none;
}

.info-wrap{
  font-family: Montserrat;

  & > .info-text{
    display: inline-block;
    color: #333333;
    width: 30%;
    max-width: 300px;
    padding: 15px;
    background: #ccc;
    border-radius: 100px;
    font-size: 14px;
    font-weight: 600;
  }
}

@keyframes next{
  0%{
    left: 0px;
    opacity: 1;
  }
  50%{
    left: 300px;
    opacity: 0;
  }
  50.1%{
    left: -300px;
    opacity: 0;
  }
  100%{
    left: 0px;
    opacity: 1;
  }
}

@keyframes prev{
  0%{
    left: 0px;
    opacity: 1;
  }
  50%{
    left: -300px;
    opacity: 0;
  }
  50.1%{
    left: 300px;
    opacity: 0;
  }
  100%{
    left: 0px;
    opacity: 1;
  }
}

.social{
  z-index: 1001;
  position: absolute;
  bottom: 20px;
  left: 30px;
  & .icon{
    display: inline-block;
    
    &:hover img{
      transform: scale(0.8);
    }
    
    & img{
      display: inline-block;
      height: 40px;
      width: 40px;
      position: relative;
      transition: 150ms cubic-bezier(0,.5,.5,1);
    }
  }
  
  & .icon::before{
    content: "";
    position: absolute;
    border-radius: 100px;
    top: 20px;
    left: 20px;
    transform: translate(-50%, -50%);
    height: 0px;
    width: 0px;
    background: #333;
    z-index: -1;
    transition: 150ms cubic-bezier(0,.5,.5,1);
  }
  
  & .icon:hover::before{
    height: 50px;
    width: 50px;
  }
}
View Compiled
window.onload = function(){

  var canvas = document.createElement("canvas");
  var innerBtn = document.querySelector("#cbtn1 .cbtn-i");
  var outerBtn = document.getElementById("cbtn1");
  var nextBtn = document.getElementById("nav-next");
  var prevBtn = document.getElementById("nav-prev");
  var btnTitle = document.getElementById("cbtn-title");
  var tipText = document.querySelector(".info-wrap .info-text");
  outerBtn.appendChild(canvas);
  var ctx = canvas.getContext("2d");
  w = ctx.canvas.width = outerBtn.offsetWidth;
  h = ctx.canvas.height = outerBtn.offsetHeight;
  dots=[];
  hoverFlag = false;
  clickFlag = false;
  mode = 0;
  nt = 0;
  tip = 0;

  tips = [
    "Stepping up your hover effects game!",
    "The spacing/canvas area around the button can be easily adjusted via CSS margin.",
    "Tested in IE and on various mobile devices.",
    "No libraries required!",
    "Imagine the endless possibilities :)",
    "In this case there is only one Button which is being controlled via JS.",
    "Using a black background for the best contrast.",
    "More effects coming soon..."
  ];

  modeSets = [
    {
      name: "Fireflies",
      maxDots: 75,
      maxSpeed: 3,
      minSpeed: 1,
      emitRate: 10,
      emitNum: 2,
      radius: 2,
      trail: 0.2,
      maxTime: 1500,
      minTime: 750,
      glow: 10,
      hueMin: 15,
      hueMax: 55
    },
    {
      name: "Hyper Jump",
      maxDots: 100,
      maxSpeed: 3,
      minSpeed: 1,
      emitRate: 10,
      emitNum: 3,
      radius: 1.75,
      trail: 0.06,
      maxTime: 700,
      minTime: 300,
      glow: 7,
      hueMin: 170,
      hueMax: 230
    },
    {
      name: "Focus",
      maxDots: 75,
      maxSpeed: 2,
      minSpeed: 0.5,
      emitRate: 10,
      emitNum: 2,
      radius: 7,
      trail: 1,
      maxTime: 1000,
      minTime: 500,
      glow: 0,
      hueMin: 60,
      hueMax: 130
    },
    {
      name: "Vortex",
      maxDots: 150,
      maxSpeed: 2,
      minSpeed: -2,
      emitRate: 20,
      emitNum: 5,
      radius: 7,
      trail: 1,
      maxTime: 3000,
      minTime: 1500,
      glow: 0,
      hueMin: 260,
      hueMax: 330
    }
    ,
    {
      name: "Code Red",
      maxDots: 50,
      maxSpeed: 1,
      minSpeed: 0.3,
      emitRate: 20,
      emitNum: 1,
      radius: 1.7,
      trail: 1,
      maxTime: 3000,
      minTime: 1500,
      glow: 10,
      hueMin: 0,
      hueMax: 10
    }
  ]

  function emitDots(x,y){
    if(dots.length<modeSets[mode].maxDots){
      for(var i=0; i<modeSets[mode].emitNum; i++){
        var color = Math.random()*(modeSets[mode].hueMax-modeSets[mode].hueMin)+modeSets[mode].hueMin;
        dots.push({
          x: w/2,
          y: h/2,
          v: Math.random()*(modeSets[mode].maxSpeed-modeSets[mode].minSpeed)+modeSets[mode].minSpeed,
          d: Math.random()*360,
          c: Math.random()*(5-(-5))+(-5),
          h: color,
          st: Date.now(),
          lt: Math.random()*(modeSets[mode].maxTime-modeSets[mode].minTime)+modeSets[mode].minTime
        });
      }
    }
  }

  function draw(){
    nt += 0.0005;
    ctx.fillStyle = "rgba(0,0,0,"+modeSets[mode].trail+")";
    ctx.fillRect(0,0,w,h);
    ctx.fill();
    for(var i=0; i<dots.length; i++){
      var pct = (Date.now()-dots[i].st)/dots[i].lt;

      switch(mode){
        case 0:
          ctx.save();
          ctx.beginPath();
          ctx.fillStyle = "hsla("+dots[i].h+", 100%, 60%, "+(1-pct)+")";
          ctx.shadowColor = "hsla("+dots[i].h+", 100%, 60%, 1)";
          ctx.shadowBlur = modeSets[mode].glow;
          ctx.arc(dots[i].x, dots[i].y, Math.pow(modeSets[mode].radius,2)/dots[i].v, 0, Math.PI*2);
          ctx.fill();
          ctx.closePath();
          ctx.restore();

          dots[i].x += dots[i].v * Math.cos(dots[i].d * Math.PI/180);
          dots[i].y += dots[i].v * Math.sin(dots[i].d * Math.PI/180);
          dots[i].d += dots[i].c;

          if(clickFlag)
            dots[i].v = 1;
          break;
        case 1:
          ctx.save();
          ctx.beginPath();
          ctx.fillStyle = "hsla("+dots[i].h+", 100%, 70%, "+(1-pct)+")";
          ctx.shadowColor = "hsla("+dots[i].h+", 100%, 70%, 1)";
          ctx.shadowBlur = modeSets[mode].glow;
          ctx.arc(dots[i].x, dots[i].y, Math.pow(modeSets[mode].radius,2)/dots[i].v, 0, Math.PI*2);
          ctx.fill();
          ctx.closePath();
          ctx.restore();

          dots[i].x += dots[i].v * Math.cos(dots[i].d * Math.PI/180);
          dots[i].y += dots[i].v * Math.sin(dots[i].d * Math.PI/180);
          if(clickFlag)
            dots[i].v = 3;
          break;
        case 2:
          ctx.save();
          ctx.beginPath();
          ctx.fillStyle = "hsla("+dots[i].h+", 100%, 70%, "+(1-pct)+")";
          ctx.shadowColor = "hsla("+dots[i].h+", 100%, 70%, 1)";
          ctx.shadowBlur = modeSets[mode].glow;
          ctx.arc(dots[i].x, dots[i].y, modeSets[mode].radius, 0, Math.PI*2);
          ctx.fill();
          ctx.closePath();
          ctx.restore();

          dots[i].x += dots[i].v * Math.cos(dots[i].d * Math.PI/180);
          dots[i].y += dots[i].v * Math.sin(dots[i].d * Math.PI/180);
          if(clickFlag)
            dots[i].v = 0.3;
          break;
        case 3:
          ctx.save();
          ctx.beginPath();
          ctx.translate(w/2,h/2);
          ctx.rotate(dots[i].d*Math.PI/180);
          ctx.fillStyle = "hsla("+dots[i].h+", 100%, 70%, "+(pct)+")";
          ctx.shadowColor = "hsla("+dots[i].h+", 100%, 70%, 1)";
          ctx.shadowBlur = modeSets[mode].glow;
          ctx.rect(dots[i].x, dots[i].y, modeSets[mode].radius, modeSets[mode].radius);
          ctx.fill();
          ctx.closePath();
          ctx.restore();

          dots[i].x += dots[i].v;
          dots[i].y += dots[i].v;
          if(clickFlag)
            dots[i].v = 3;
          break;
        case 4:
          var sd = Math.pow(modeSets[mode].radius,2)/dots[i].v;
          ctx.save();
          ctx.beginPath();
          ctx.strokeStyle = "hsla("+dots[i].h+", 100%, 50%, "+(1-pct)+")";
          ctx.shadowColor = "hsla("+dots[i].h+", 100%, 50%, 1)";
          ctx.shadowBlur = modeSets[mode].glow;
          if(clickFlag){
            ctx.arc(dots[i].x, dots[i].y, sd, 0, Math.PI*2);
          }else{
            ctx.rect(dots[i].x-sd, dots[i].y-sd, sd*2, sd*2);
          }
          ctx.stroke();
          ctx.closePath();
          ctx.restore();

          dots[i].x += dots[i].v * Math.cos(dots[i].d * Math.PI/180);
          dots[i].y += dots[i].v * Math.sin(dots[i].d * Math.PI/180);
          break;
      }

      if(dots[i].x>w || dots[i].x<0 || dots[i].y>h || dots[i].y<0 || dots[i].st+dots[i].lt<Date.now()){
        dots.splice(i,1);
      }
    }
    anim = requestAnimationFrame(draw);
  }

  innerBtn.onmouseover = function(){
    hoverFlag = true;
    emitter = setInterval(emitDots, modeSets[mode].emitRate);
    anim = requestAnimationFrame(draw);
  }

  innerBtn.onmouseout = function(){
    hoverFlag = false;
    clearInterval(emitter);
    cancelAnimationFrame(anim);
    ctx.clearRect(0,0,w,h);
    dots = [];
  }

  innerBtn.onmousedown = function(){
    clickFlag = true;
  }

  innerBtn.onmouseup = function(){
    clickFlag = false;
  }

  btnTitle.innerHTML = modeSets[mode].name;

  nextBtn.onclick = function(){
    if(modeSets.length <= mode+1){
      mode = 0;
    }else{
      mode += 1;
    }

    setTimeout(function(){
      innerBtn.setAttribute("data-mode", mode);
      btnTitle.innerHTML = modeSets[mode].name;
    }, 300);

    outerBtn.classList.add("next_anim");
    btnTitle.classList.add("prev_anim");
    setTimeout(function(){
      outerBtn.classList.remove("next_anim");
      btnTitle.classList.remove("prev_anim");
    }, 600)
  }

  prevBtn.onclick = function(){
    if(0 > mode-1){
      mode = modeSets.length-1;
    }else{
      mode -= 1;
    }

    setTimeout(function(){
      innerBtn.setAttribute("data-mode", mode);
      btnTitle.innerHTML = modeSets[mode].name;
    }, 300);

    outerBtn.classList.add("prev_anim");
    btnTitle.classList.add("next_anim");
    setTimeout(function(){
      outerBtn.classList.remove("prev_anim");
      btnTitle.classList.remove("next_anim");
    }, 600)
  }

  tipText.innerHTML = tips[tip];
  setInterval(function(){
    tips.length<=tip+1?tip=0:tip+=1;
    tipText.innerHTML = tips[tip];
  }, 7000)

}







// Hey! Wow, you found a comment. Thanks for checking this Pen out :)

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css

External JavaScript

This Pen doesn't use any external JavaScript resources.