Hi! I have been trying to inject custom code into my Readymag site in order to make a short line of text the “cursor” instead of the default. I have exhausted everything I know to do to achieve this. I was able to effectively hide the default cursor in most scenarios, even as I navigate pages. Still, when the browser is in full-screen mode, something is overriding my JS, and the cursor reappears and stays on screen until I refresh or the mouse leaves the screen. This is the current code I am using:
AFTER :
<div class="cursor-tagline" data-id="698805bcdc1b184afb0e6b3d">Constructing worlds for moving and still image.</div>
BEFORE :
<script>
(function () {
// ── Config ──────────────────────────────────────────────
var TAGLINE_ID = "698805bcdc1b184afb0e6b3d";
var OFFSET_X = 8; // px right of cursor
var OFFSET_Y = 10; // px below cursor
var IDLE_MS = 80; // ms before tagline fades out
var OBSERVE_MAX = 15000; // stop watching DOM after 15s
// ────────────────────────────────────────────────────────
var selector = '[data-id="' + TAGLINE_ID + '"]';
function init(el) {
// Don't run twice on the same element
if (!el || el.__cursorInit) return;
el.__cursorInit = true;
// Keep the tagline out of the normal document flow
el.style.setProperty("position", "absolute", "important");
// ── Stage: find the container that fills the viewport ──
var stage = pickStage();
var stageRect = stage.getBoundingClientRect(); // cached
function pickStage() {
var vw = window.innerWidth, vh = window.innerHeight;
var node = el.parentElement;
while (node && node !== document.body) {
var r = node.getBoundingClientRect();
if (r.width >= vw * 0.9 && r.height >= vh * 0.9) return node;
node = node.parentElement;
}
return document.body;
}
// Refresh cached rect on resize (not every frame)
window.addEventListener("resize", function () {
stage = pickStage();
stageRect = stage.getBoundingClientRect();
}, { passive: true });
// ── Cursor state ───────────────────────────────────────
var cursorX = 0, cursorY = 0;
var hasMoved = false;
var lastMoved = performance.now();
var rafId = null;
// ── Animation loop (only runs when cursor is active) ───
function frame() {
var now = performance.now();
if (hasMoved) {
// Convert viewport coords → stage-local coords
var x = (cursorX - stageRect.left) + OFFSET_X;
var y = (cursorY - stageRect.top) + OFFSET_Y;
el.style.setProperty("left", x + "px", "important");
el.style.setProperty("top", y + "px", "important");
el.classList.add("is-on");
hasMoved = false;
}
// Fade out after idle threshold
if (now - lastMoved > IDLE_MS) {
el.classList.remove("is-on");
}
// Keep looping only while cursor is active;
// stop after a short idle to save CPU/battery
if (now - lastMoved < IDLE_MS + 2000) {
rafId = requestAnimationFrame(frame);
} else {
rafId = null; // loop paused — restarts on next mousemove
}
}
// ── Events ─────────────────────────────────────────────
window.addEventListener("mousemove", function (e) {
cursorX = e.clientX;
cursorY = e.clientY;
hasMoved = true;
lastMoved = performance.now();
// Restart the loop if it went idle
if (!rafId) rafId = requestAnimationFrame(frame);
}, { passive: true });
window.addEventListener("mouseleave", function () {
el.classList.remove("is-on");
});
} // end init()
// ── Wait for the element to appear in the DOM ───────────
// (ReadyMag injects elements dynamically, so we can't
// assume the tagline exists at script-run time.)
var obs = new MutationObserver(function () {
var el = document.querySelector(selector);
if (el) {
init(el);
obs.disconnect();
}
});
obs.observe(document.documentElement, { childList: true, subtree: true });
// Failsafe: stop observing after 15 seconds
setTimeout(function () { obs.disconnect(); }, OBSERVE_MAX);
// Also try immediately in case the element already exists
var existing = document.querySelector(selector);
if (existing) { init(existing); obs.disconnect(); }
})();
// Force cursor back to hidden after every click
window.addEventListener("click", function () {
// Hammer cursor hidden every 16ms for 2 seconds after any click
// This covers the entire duration of Readymag's page transition
var hammerId = null;
var hammerCount = 0;
var MAX = 120; // 120 × 16ms = ~2 seconds
function hammer() {
enforce();
injectStyle();
hammerCount++;
if (hammerCount < MAX) {
hammerId = setTimeout(hammer, 16);
}
}
if (hammerId) clearTimeout(hammerId);
hammerCount = 0;
hammer();
}, true);
</script>
<script>
(function () {
var style = document.createElement("style");
style.textContent = [
"html, html *, html *:hover,",
"html *:active, html *:focus,",
"html *:focus-visible,",
".mag, .mag *, .mag-pages-container,",
".mag-pages-container *, .page,",
".page *, .center-page, .center-page *,",
".prev-page, .prev-page *,",
".next-page, .next-page * {",
" cursor: none !important;",
"}"
].join("\n");
function injectStyle() {
if (!document.head.contains(style)) {
document.head.appendChild(style);
}
// Stamp it directly on the html element as a fallback
document.documentElement.setAttribute("style",
(document.documentElement.getAttribute("style") || "") +
"; cursor: none !important;"
);
}
injectStyle();
// Re-inject if Readymag removes it during a transition
var obs = new MutationObserver(injectStyle);
obs.observe(document.head, { childList: true });
// Also watch the html element's own attributes
var obsHtml = new MutationObserver(enforce);
obsHtml.observe(document.documentElement, {
attributes: true,
attributeFilter: ["style", "class"]
});
// Hammer the body style directly on any interaction
function enforce() {
document.documentElement.style.setProperty("cursor", "none", "important");
document.body.style.setProperty("cursor", "none", "important");
}
window.addEventListener("mousemove", enforce, { passive: true });
window.addEventListener("mousedown", enforce, { passive: true });
window.addEventListener("click", enforce, true);
window.addEventListener("mouseup", enforce, true);
})();
</script>
CSS:
/* ── Cursor-follow tagline ─────────────────────────────── */
[data-id="698805bcdc1b184afb0e6b3d"] {
position: absolute !important;
left: 0 !important;
top: 0 !important;
pointer-events: none !important;
z-index: 999999 !important;
opacity: 0 !important;
mix-blend-mode: difference !important;
transition: opacity 120ms linear !important;
transform: none !important;
will-change: left, top, opacity;
font-family: "Times New Roman", Times, serif !important;
font-size: 17pt !important;
color: #ffffff !important;
}
[data-id="698805bcdc1b184afb0e6b3d"] * {
color: #ffffff !important;
font-family: "Times New Roman", Times, serif !important;
font-size: 17pt !important;
}
[data-id="698805bcdc1b184afb0e6b3d"].is-on {
opacity: 1 !important;
}
If anyone has suggestions it would be much appreciated. I’m not even sure this can be done haha