UNPKG

easy-back-to-top

Version:

A lightweight, zero-dependency JavaScript utility that adds a customizable 'Back to Top' button with optional scroll progress. Framework-free, CDN-ready, and easy to use.

1 lines 3.42 kB
class EasyBackToTop{constructor(t={}){this.options={position:"bottom-right",offset:100,size:50,backgroundColor:"#007bff",iconColor:"#fff",iconSize:24,zIndex:9999,showOnScroll:!0,showProgress:!1,progressColor:"#ffffff88",progressWidth:3,...t},this.button=null,this.visible=!1,this.progressCircle=null,this.#t()}#t(){this.button=this.#s(),this.options.showOnScroll||this.options.showProgress?window.addEventListener("scroll",(()=>this.#e())):this.button.style.display="block"}#s(){const t=document.createElement("div");t.className="easy-back-to-top",t.style.position="fixed",t.style.bottom="20px",t.style.right="bottom-right"===this.options.position?"20px":"auto",t.style.left="bottom-left"===this.options.position?"20px":"auto",t.style.width=`${this.options.size}px`,t.style.height=`${this.options.size}px`,t.style.backgroundColor=this.options.backgroundColor,t.style.borderRadius="50%",t.style.display="none",t.style.alignItems="center",t.style.justifyContent="center",t.style.cursor="pointer",t.style.zIndex=this.options.zIndex,t.style.transition="opacity 0.3s ease",t.style.boxShadow="0 4px 10px rgba(0,0,0,0.2)",t.style.position="fixed";const s=document.createElement("div");if(s.innerHTML=`\n <svg xmlns="http://www.w3.org/2000/svg" width="${this.options.iconSize}" height="${this.options.iconSize}" viewBox="0 0 24 24" fill="none" stroke="${this.options.iconColor}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="18 15 12 9 6 15" />\n </svg>\n `,s.style.position="relative",s.style.zIndex=2,t.appendChild(s),this.options.showProgress){const s="http://www.w3.org/2000/svg",e=this.options.size,o=e/2-this.options.progressWidth/2,i=2*Math.PI*o,n=document.createElementNS(s,"svg");n.setAttribute("width",e),n.setAttribute("height",e),n.style.position="absolute",n.style.top="0",n.style.left="0",n.style.transform="rotate(-90deg)",n.style.zIndex=1;const r=document.createElementNS(s,"circle");r.setAttribute("cx",e/2),r.setAttribute("cy",e/2),r.setAttribute("r",o),r.setAttribute("stroke",this.options.progressColor),r.setAttribute("stroke-width",this.options.progressWidth),r.setAttribute("fill","none"),r.setAttribute("opacity","0.2");const l=document.createElementNS(s,"circle");l.setAttribute("cx",e/2),l.setAttribute("cy",e/2),l.setAttribute("r",o),l.setAttribute("stroke",this.options.progressColor),l.setAttribute("stroke-width",this.options.progressWidth),l.setAttribute("fill","none"),l.setAttribute("stroke-dasharray",i),l.setAttribute("stroke-dashoffset",i),l.style.transition="stroke-dashoffset 0.2s linear",n.appendChild(r),n.appendChild(l),t.appendChild(n),this.progressCircle=l,this.progressCircumference=i}return t.addEventListener("mouseenter",(()=>t.style.opacity=.85)),t.addEventListener("mouseleave",(()=>t.style.opacity=1)),t.onclick=()=>{window.scrollTo({top:0,behavior:"smooth"})},document.body.appendChild(t),t}#e(){const t=window.scrollY||document.documentElement.scrollTop,s=t/(document.documentElement.scrollHeight-window.innerHeight)*100;if(t>this.options.offset&&!this.visible?(this.button.style.display="flex",this.visible=!0):t<=this.options.offset&&this.visible&&(this.button.style.display="none",this.visible=!1),this.options.showProgress&&this.progressCircle){const t=this.progressCircumference-s/100*this.progressCircumference;this.progressCircle.setAttribute("stroke-dashoffset",t)}}}window.EasyBackToTop=EasyBackToTop;