Pointer Bookmarklet

A ring around the cursor for screen shares—no extension, no always-on software.

I took my son to his first drum lesson. The teacher put a PDF on a big white screen, and I could barely follow the cursor. Same thing happens on work calls when I'm sharing my screen: I want people to look there, and the default pointer doesn't cut it.

I didn't want another menu-bar app or a Chrome extension chewing RAM 24/7. A bookmarklet is enough: click once and a circle follows the mouse; click again and it goes away.

Features

  • Toggle with one click — On/off from the same bookmark.
  • Contrast-aware color — The ring picks a color that tends to read against whatever is behind the cursor (cyan vs magenta style).
  • Optional motion tail — Press Ctrl+6+7+8 (in order, with Ctrl held) for a more obvious trail; same combo turns it off.
  • Zero install footprint — It's a bookmark, not a background service.

How to use it

  1. Install the bookmark (drag the button at the top or bottom of this page to your bookmarks bar, or paste the code below into a bookmark URL).
  2. On any normal web page, click the bookmark to turn the highlight on.
  3. Click again to remove it.
  4. If you need the tail, use the Ctrl+6+7+8 chord once to enable and once to disable.

Install (alternate)

If drag-and-drop is awkward: copy everything inside the code block below, create a new bookmark, paste into the URL field, and save.

Bookmarklet Code:

javascript:(function(){if(window.cursorHighlighter){window.cursorHighlighter.remove();window.cursorHighlighter=null;window.cursorHighlighterCanvas?.remove();window.cursorHighlighterCanvas=null;cancelAnimationFrame(window.cursorHighlighterAnim);document.removeEventListener('mousemove',window.cursorHighlighterMove);document.removeEventListener('click',window.cursorHighlighterClick);document.removeEventListener('keydown',window.cursorHighlighterKey);window.cursorHighlighterKeySeq=null;window.cursorHighlighterParticles=null;return;}const ball=document.createElement('div');ball.id='cursor-highlighter';ball.style.cssText='position:fixed;width:36px;height:36px;border-radius:50%;pointer-events:none;z-index:2147483647;transition:transform 0.15s ease,box-shadow 0.15s ease;mix-blend-mode:difference;border:2px solid;';document.body.appendChild(ball);const canvas=document.createElement('canvas');canvas.style.cssText='position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:2147483646;display:none;';canvas.width=window.innerWidth;canvas.height=window.innerHeight;document.body.appendChild(canvas);const ctx=canvas.getContext('2d');let currentColor='#00FFFF';let tailEnabled=false;let cursor={x:0,y:0};let particles=[];const particleCount=25;const trailSpeed=0.4;function getContrastColor(x,y){const el=document.elementFromPoint(x,y);if(!el)return'#00FFFF';const bg=window.getComputedStyle(el).backgroundColor;const match=bg.match(/\d+/g);if(!match||match.length<3)return'#00FFFF';const r=parseInt(match[0]),g=parseInt(match[1]),b=parseInt(match[2]);const luminance=0.299*r+0.587*g+0.114*b;return luminance>128?'#FF00FF':'#00FFFF';}function hexToRgb(hex){const r=parseInt(hex.slice(1,3),16);const g=parseInt(hex.slice(3,5),16);const b=parseInt(hex.slice(5,7),16);return{r,g,b};}function updateParticles(){if(!tailEnabled)return;ctx.clearRect(0,0,canvas.width,canvas.height);let x=cursor.x;let y=cursor.y;particles.forEach((particle,index)=>{const nextParticle=particles[index+1]||particles[0];particle.x=x;particle.y=y;x+=(nextParticle.x-particle.x)*trailSpeed;y+=(nextParticle.y-particle.y)*trailSpeed;});ctx.lineCap='round';ctx.lineJoin='round';const rgb=hexToRgb(currentColor);for(let i=1;i<particles.length;i++){const progress=i/particles.length;const alpha=1-progress;const width=15*(1-progress);ctx.strokeStyle=`rgba(${rgb.r},${rgb.g},${rgb.b},${alpha})`;ctx.lineWidth=width;ctx.beginPath();ctx.moveTo(particles[i-1].x,particles[i-1].y);ctx.lineTo(particles[i].x,particles[i].y);ctx.stroke();}}function animLoop(){updateParticles();window.cursorHighlighterAnim=requestAnimationFrame(animLoop);}window.cursorHighlighterMove=function(e){const color=getContrastColor(e.clientX,e.clientY);ball.style.left=(e.clientX-18)+'px';ball.style.top=(e.clientY-18)+'px';ball.style.backgroundColor=color;ball.style.borderColor=color;ball.style.boxShadow='none';currentColor=color;cursor.x=e.clientX;cursor.y=e.clientY;if(tailEnabled&&particles.length===0){for(let i=0;i<particleCount;i++){particles.push({x:cursor.x,y:cursor.y});}}};window.cursorHighlighterClick=function(e){ball.style.transform='scale(0.7)';ball.style.boxShadow=`0 0 20px ${currentColor}, 0 0 40px ${currentColor}, 0 0 60px ${currentColor}`;setTimeout(()=>{ball.style.transform='scale(1)';ball.style.boxShadow='none';},150);};let keySeq='';let keyTimer;window.cursorHighlighterKey=function(e){if(e.ctrlKey){keySeq+=e.key;clearTimeout(keyTimer);keyTimer=setTimeout(()=>keySeq='',1000);if(keySeq.includes('678')){tailEnabled=!tailEnabled;canvas.style.display=tailEnabled?'block':'none';if(tailEnabled){particles=[];for(let i=0;i<particleCount;i++){particles.push({x:cursor.x,y:cursor.y});}}else{particles=[];ctx.clearRect(0,0,canvas.width,canvas.height);}keySeq='';}}};window.addEventListener('resize',()=>{canvas.width=window.innerWidth;canvas.height=window.innerHeight;});document.addEventListener('mousemove',window.cursorHighlighterMove);document.addEventListener('click',window.cursorHighlighterClick);document.addEventListener('keydown',window.cursorHighlighterKey);animLoop();window.cursorHighlighter=ball;window.cursorHighlighterCanvas=canvas;window.cursorHighlighterParticles=particles;})();