Turn your team cards into an interactive experience with a custom cursor CTA.
Category
Built with
Widgets
Custom code
CSS
JS
Custom css
The CSS to make the animation for this power up is included in the top level parent container Advanced > Custom CSS. No additional setup needed. Just copy the component and the styles come with it.
/* Hide cursor inside each team card (desktop only) */
@media (min-width: 1025px) {
.team-card,
.team-card * {
cursor: none !important;
}
}
/* =========================
Cursor pill wrapper
========================= */
.eui-cursor-cta {
position: fixed;
top: 0;
left: 0;
transform: translate(-50%, -50%); /* centered on the mouse */
z-index: 999; /* stays above everything */
/* IMPORTANT: prevents flicker by stopping the pill stealing hover */
pointer-events: none;
opacity: 0;
visibility: hidden;
transition: opacity 160ms ease, visibility 160ms ease;
font-family: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
font-weight: 600;
}
.eui-cursor-cta.is-active {
opacity: 1;
visibility: visible;
}
/* =========================
Cursor pill styling
This targets BOTH setups:
- <div class="eui-cursor-inner"> ... </div>
- OR <a> ... </a>
Edit safely in the sections below.
========================= */
.eui-cursor-cta .eui-cursor-inner,
.eui-cursor-cta > a {
display: inline-flex !important;
align-items: center !important;
gap: 10px !important;
/* =========================
EDIT: SIZING
========================= */
padding: 12px 16px !important;
border-radius: 999px !important;
font-size: 14px !important;
line-height: 1 !important;
/* =========================
EDIT: COLORS
========================= */
background-color: rgba(11, 31, 58, 0.88) !important; /* pill background */
border: 2px solid rgba(20, 184, 166, 0.18) !important; /* pill border */
color: #fff !important;
/* =========================
EDIT: EFFECTS (optional)
- Remove blur if you don't want the glass look
========================= */
backdrop-filter: blur(10px) !important;
-webkit-backdrop-filter: blur(10px) !important;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45) !important;
white-space: nowrap !important;
opacity: 1 !important;
background-image: none !important;
}
/* If the pill is an <a>, remove default link styles */
.eui-cursor-cta > a {
text-decoration: none !important;
}
/* =========================
Safety: prevent theme effects from breaking the pill
(Usually leave this alone)
========================= */
.eui-cursor-cta,
.eui-cursor-cta * {
mix-blend-mode: normal !important;
filter: none !important;
}
/* =========================
Tablet/mobile: disable the pill entirely
(So you can use normal LinkedIn icons/links instead)
========================= */
@media (max-width: 1024px) {
.eui-cursor-cta {
display: none !important;
}
.team-card,
.team-card * {
cursor: auto !important;
}
}
/* =========================
Accessibility: reduced motion
========================= */
@media (prefers-reduced-motion: reduce) {
.eui-cursor-cta {
transition: none !important;
}
}
Custom Javascript
JavaScript is loaded via a HTML widget. Don’t remove it – it powers the animation.
<script>
(function () {
const isDesktop = window.matchMedia("(min-width: 1025px)").matches;
const canHover = window.matchMedia("(hover: hover) and (pointer: fine)").matches;
if (!isDesktop || !canHover) return;
// Create the floating cursor pill (visual only)
const cursor = document.createElement("div");
cursor.className = "eui-cursor-cta";
cursor.innerHTML = `
<div class="eui-cursor-inner">
<span>View LinkedIn Profile</span>
<span aria-hidden="true">↗</span>
</div>
`;
document.body.appendChild(cursor);
let activeCard = null;
let activeUrl = null;
let lastX = 0;
let lastY = 0;
let rafId = null;
function render() {
cursor.style.left = lastX + "px";
cursor.style.top = lastY + "px";
rafId = null;
}
function onMove(e) {
lastX = e.clientX;
lastY = e.clientY;
if (!rafId) rafId = requestAnimationFrame(render);
// Determine what's under the cursor (ignores the pill because it's pointer-events:none)
const el = document.elementFromPoint(e.clientX, e.clientY);
const card = el && el.closest ? el.closest(".team-card") : null;
if (!card) {
deactivate();
return;
}
activate(card);
}
function getCardLink(card) {
const attrUrl = card.getAttribute("data-linkedin");
if (attrUrl) return attrUrl;
const a = card.querySelector('a[href]:not([href="#"]):not([href=""])');
if (a && a.href) return a.href;
if (card.tagName === "A" && card.href) return card.href;
return null;
}
function activate(card) {
if (activeCard === card) return;
const url = getCardLink(card);
if (!url) return;
activeCard = card;
activeUrl = url;
cursor.classList.add("is-active");
}
function deactivate() {
activeCard = null;
activeUrl = null;
cursor.classList.remove("is-active");
}
// Track mouse globally (desktop only)
window.addEventListener("mousemove", onMove, { passive: true });
// Click anywhere on the active card opens the link
document.addEventListener("click", (e) => {
if (!activeCard || !activeUrl) return;
const clickedCard = e.target.closest && e.target.closest(".team-card");
if (clickedCard !== activeCard) return;
// Let normal links inside the card behave normally
const clickedLink = e.target.closest && e.target.closest("a");
if (clickedLink) return;
window.open(activeUrl, "_blank", "noopener,noreferrer");
});
window.addEventListener("blur", deactivate);
})();
</script>