Is it possible to run a piece of JavaScript on mobile/tablet devices only? I'd like to do something a bit better than display: none
and it makes sense to stop the script from running if it's not required.
Basically I have a custom cursor effect, that is only required when it follows the cursor on desktop with a mouse/trackpad.
This is the script I have:
var cursor = document.querySelector('.cursor-outer');
var cursorinner = document.querySelector('.cursor');
var a = document.querySelectorAll('a');
var moveCursor = true;
var radiusOfCursor = parseInt(getComputedStyle(cursor).getPropertyValue('width')) / 2; // radiusOfCursor = (width_of_cursor / 2).
document.addEventListener('mousemove', function (e) {
var x = e.clientX;
var y = e.clientY;
cursorinner.style.left = x + 'px';
cursorinner.style.top = y + 'px';
if (!moveCursor) return;
cursor.style.marginLeft = `calc(${e.clientX}px - ${radiusOfCursor}px)`;
cursor.style.marginTop = `calc(${e.clientY}px - ${radiusOfCursor}px)`;
moveCursor = false;
setTimeout(() => {
moveCursor = true;
}, 32) // The wait time. I chose 95 because it seems to work just fine for me.
});
/* Centre pointer after stopping */
function mouseMoveEnd() {
cursor.style.marginLeft = `calc(${cursorinner.style.left} - ${radiusOfCursor}px)`;
cursor.style.marginTop = `calc(${cursorinner.style.top} - ${radiusOfCursor}px)`;
}
var x;
document.addEventListener('mousemove', function() {
if (x) clearTimeout(x);
x = setTimeout(mouseMoveEnd, 10);
}, false);
/* End */
document.addEventListener('mousedown', function() {
cursor.classList.add('click');
cursorinner.classList.add('cursorinnerhover');
});
document.addEventListener('mouseup', function() {
cursor.classList.remove('click');
cursorinner.classList.remove('cursorinnerhover');
});
a.forEach(item => {
item.addEventListener('mouseover', () => {
cursor.classList.add('hover');
});
item.addEventListener('mouseleave', () => {
cursor.classList.remove('hover');
});
});
a.forEach((item) => {
const interaction = item.dataset.interaction;
item.addEventListener("mouseover", () => {
cursorinner.classList.add(interaction);
});
item.addEventListener("mouseleave", () => {
cursorinner.classList.remove(interaction);
});
});
* {
cursor: none;
}
.cursor-outer {
border: 2px solid black;
border-radius: 100%;
box-sizing: border-box;
height: 32px;
pointer-events: none;
position: fixed;
top: 16px;
left: 16px;
transform: translate(-50%, -50%);
transition: height .12s ease-out, margin .12s ease-out, opacity .12s ease-out, width .12s ease-out;
width: 32px;
z-index: 100;
}
.cursor {
background-color: black;
border-radius: 100%;
height: 4px;
opacity: 1;
position: fixed;
transform: translate(-50%, -50%);
pointer-events: none;
transition: height .12s, opacity .12s, width .12s;
width: 4px;
z-index: 100;
}
<div class="cursor-outer"></div>
<div class="cursor"></div>
You can use something similar to this to determine if a device is touch-enabled:
isTouchDevice = () => {
return ( 'ontouchstart' in window ) ||
( navigator.maxTouchPoints > 0 ) ||
( navigator.msMaxTouchPoints > 0 );
};
This is adapted from Patrick H. Lauke's Detecting touch article on Mozilla.
Then just: if (isTouchDevice()) { /* Do touch screen stuff */}
But maybe a pure CSS approach could work better in your situation, like:
@media (hover: none) {
.cursor {
pointer-events: none;
}
}
If you don't mind using a third-party library, then Modernizr is really great for detecting things like this in the user's environment. Specifically, Modernizr.pointerevents
will confirm if touchscreen is being used.