SHARE
To create this eye-catching cursor effect, the first step involves establishing three distinct sections in Elementor. The layout consists of a top section, an interactive middle section, and a bottom section. Each section should be set to full width and 100vh height, ensuring complete viewport coverage. The interactive middle section, which hosts our primary cursor effect, requires a specific class name “interactive-section” for proper functionality.
The magic happens through a combination of HTML and CSS code implementations. The custom cursor is built using GSAP (GreenSock Animation Platform) for smooth animations, while CSS handles the styling aspects. The cursor’s behavior is programmed to grow and transform when entering the interactive section, creating an engaging user experience.
One of the most intriguing aspects of this cursor animation is the mix-blend-mode property set to “difference.” This creates a unique color-inverting effect where:
– When cursor and background colors are identical, the result appears black
– Complementary colors produce white
– Black cursors should be avoided as they won’t create the desired effect
The color calculations follow a simple formula: foreground color minus background color, using RGB values to determine the final appearance.
The tutorial offers several ways to customize the cursor effect:
1. Size Adjustments:
– Modify the cursor size within the interactive section through GSAP code
– Adjust the standard cursor size for non-interactive sections
– Control animation duration and easing functions
2. Color Modifications:
– Change cursor background colors using hex values or RGB
– Experiment with different color combinations for various blend effects
3. Cursor Visibility:
– Option to display smaller cursors in non-interactive sections
– Ability to completely hide the default mouse cursor
– Control cursor transition behaviors between sections
For optimal implementation, consider these key points:
– Ensure class names in your HTML match exactly with the provided code
– Position the HTML widget at the end of your custom container section
– Maintain consistent cursor sizes across different sections for smooth transitions
– Test color combinations thoroughly to achieve desired blend effects
When implementing this custom cursor, keep in mind:
– The solution of the video requires Elementor Pro, still you can build it in Elementor Free
– CSS class names must match exactly with the provided code
– The mix-blend-mode calculations affect color choices
– Proper positioning of HTML widgets is crucial for functionality
Through this implementation, websites can achieve a modern, interactive feel that engages users and enhances the overall browsing experience. The combination of GSAP animations and CSS blend modes creates a sophisticated effect that can be customized to match any brand’s color scheme and design preferences.
This custom cursor solution offers both functionality and flexibility, allowing developers and designers to create unique interactive experiences while maintaining smooth performance across different sections of their websites. Whether used for creative portfolios, modern business sites, or interactive landing pages, this cursor effect adds a layer of sophistication to any web project.
Create a new Page
Add Three Sections or use your existing layout
The section in the middle will become our “Interactive-section” in which the custom cursor becomes active
Add your Layout in the interactive section
Add HTML Widget at the bottom of the interactive-section container
Add GSAP Code from below
Go to the Interactive-section main container and go to Advanced tab and use Custom CSS (Elementor Pro Users) and add the CSS code from below. If you don’t want to see the normal cursor see my variations and also add there the additional code. Elementor Free users can add the code to the Custom CSS of Elementor and not directly in the Container widget.
Save and preview: Note that Javascript is usually only visible on the Preview and Live Pages.
The mix-blend-mode: difference is a powerful tool for creating dynamic visual effects. It calculates the absolute difference between the colors of overlapping elements.
For each color channel (Red, Green, Blue), the formula is:
Formula:
Difference = | Foreground Color – Background Color |
Example 1: Yellow Cursor on Yellow Text
When both the cursor and the text are yellow (rgb(255, 255, 0)):
Red Channel: |255 – 255| = 0
Green Channel: |255 – 255| = 0
Blue Channel: |0 – 0| = 0
Resulting Color:
rgb(0, 0, 0) (Black)
Example 2: Yellow Cursor on Blue Text
Cursor Color: Yellow (rgb(255, 255, 0)) Text Color: Blue (rgb(0, 0, 255)) Calculations:
Red Channel: |255 – 0| = 255
Green Channel: |255 – 0| = 255
Blue Channel: |0 – 255| = 255
Resulting Color:
rgb(255, 255, 255) (White)
<script src=”https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js”></script>
<script>
// Create the cursor element and add it to the DOM
const cursor = document.createElement(‘div’);
cursor.classList.add(‘custom-cursor’);
document.body.appendChild(cursor);
gsap.set(cursor, { x: -100, y: -100 });
if (‘ontouchstart’ in window || navigator.maxTouchPoints > 0) {
// Hide custom cursor for touch devices
cursor.style.display = ‘none’;
} else {
// Function for cursor movement
let throttleTimeout;
document.addEventListener(‘mousemove’, (e) => {
if (!throttleTimeout) {
throttleTimeout = setTimeout(() => {
gsap.to(cursor, {
x: e.clientX – cursor.offsetWidth / 2,
y: e.clientY – cursor.offsetHeight / 2,
duration: 0,
ease: “none”,
force3D: true
});
throttleTimeout = null;
}, 16); // ~60fps (1000ms / 60)
}
});
// Capture interactive sections
const interactiveSections = document.querySelectorAll(‘.interactive-section’);
// Show Custom Cursor only in specific sections
interactiveSections.forEach(section => {
section.addEventListener(‘mouseenter’, () => {
cursor.style.display = ‘block’; // Show custom cursor
cursor.classList.add(‘active’);
// Cursor grows when hovering over section
gsap.to(cursor, {
width: 200,
height: 200,
duration: 0.3,
ease: “power2.out”,
force3D: true
});
});
section.addEventListener(‘mouseleave’, () => {
cursor.style.display = ‘none’; // Hide custom cursor
cursor.classList.remove(‘active’);
});
});
// Hide cursor outside interactive sections
document.addEventListener(‘mousemove’, (e) => {
const inInteractiveSection = Array.from(interactiveSections).some(section =>
section.contains(e.target)
);
if (!inInteractiveSection) {
cursor.style.display = ‘none’; // Hide custom cursor
}
});
}
</script>
If you want to see the standard cursor in the “interactive-section” then delete the style for the interactive-section on the last three rows.
Change here the background color for the Custom Cursor in Line 10 !!! It is set to white in code below.
.custom-cursor {
display: flex;
justify-content: center; /* Horizontally center */
align-items: center; /* Vertically center */
position: fixed;
top: 0;
left: 0;
width: 0px;
height: 0px;
background: #ffffff;
mix-blend-mode: difference;
border-radius: 50%;
border: 1px solid rgba(255, 255, 255, 0.3);
pointer-events: none;
z-index: 9999;
transition: none;
opacity: 1;
will-change: transform; /* Wichtig für Performance */
backface-visibility: hidden;
transform: translate3d(0,0,0);
}
.interactive-section{
cursor: none;
}
Make sure to add a height and width in the CSS Code and in the GSAP code. Make sure to have the same values. It ensures to have start values for the custom cursor.
If you want to see the standard cursor in the “interactive-section” then delete the style for the interactive-section on the last three rows.
Change here the background color for the Custom Cursor in Line 10 !!! It is set to white in code below.
If you want to hide the normal mouse cursor on the whole page and see only a custom cursor, then add the following CSS:
.custom-cursor {
display: flex;
justify-content: center; /* Horizontally center */
align-items: center; /* Vertically center */
position: fixed;
top: 0;
left: 0;
width: 20px;
height: 20px;
background: #ffffff;
mix-blend-mode: difference;
border-radius: 50%;
border: 1px solid rgba(255, 255, 255, 0.3);
pointer-events: none;
z-index: 9999;
transition: none;
opacity: 1;
will-change: transform; /* Important for performance */
backface-visibility: hidden;
transform: translate3d(0,0,0);
}
.interactive-section{
cursor: none;
}
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script>
// Create the cursor element and add it to the DOM
const cursor = document.createElement('div');
cursor.classList.add('custom-cursor');
document.body.appendChild(cursor);
gsap.set(cursor, { x: -100, y: -100 });
if ('ontouchstart' in window || navigator.maxTouchPoints > 0) {
// Hide custom cursor for touch devices
cursor.style.display = 'none';
} else {
// Function for cursor movement
let throttleTimeout;
document.addEventListener('mousemove', (e) => {
if (!throttleTimeout) {
throttleTimeout = setTimeout(() => {
gsap.to(cursor, {
x: e.clientX - cursor.offsetWidth / 2,
y: e.clientY - cursor.offsetHeight / 2,
duration: 0,
ease: "none",
force3D: true
});
throttleTimeout = null;
}, 16); // ~60fps (1000ms / 60)
}
});
// Capture interactive sections
const interactiveSections = document.querySelectorAll('.interactive-section');
// Show Custom Cursor only in specific sections
interactiveSections.forEach(section => {
section.addEventListener('mouseenter', () => {
cursor.style.display = 'block'; // Show custom cursor
cursor.classList.add('active');
// Cursor grows when hovering over section
gsap.to(cursor, {
width: 200,
height: 200,
duration: 0.3,
ease: "power2.out",
force3D: true
});
});
section.addEventListener('mouseleave', () => {
cursor.classList.remove('active');
// Back to Standard Size
gsap.to(cursor, {
width: 20,
height: 20,
duration: 0.2,
ease: "power2.out",
force3D: true
});
});
});
}
</script>