What's the best way to detect a 'touch screen' device using JavaScript?
Update: Please read blmstr's answer below before pulling a whole feature detection library into your project. Detecting actual touch support is more complex, and Modernizr only covers a basic use case.
Modernizr is a great, lightweight way to do all kinds of feature detection on any site.
It simply adds classes to the html element for each feature.
You can then target those features easily in CSS and JS. For example:
html.touch div {
width: 480px;
}
html.no-touch div {
width: auto;
}
And Javascript (jQuery example):
$('html.touch #popup').hide();
How detecting if the browser has touch capabilities ?
To answer the question exactly as set, if you put this function into your Javascript code you can just run it and set a flag which you can use in your code afterwards if you want to do things differently for a touchscreen.
function isTouchDevice() {
return (('ontouchstart' in window) ||
(navigator.maxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0));
}
const myFlag = isTouchDevice();
....
// example
if (myFlag) { alert('You can move the object with your finger'); }
else { alert('Use the arrow keys on your keyboard to move the object'); }
But remember a user may use the device as a touchscreen one minute and as a keyboard device the next. You can code for sensing both key and touch events and unless your site absolutely needs the user to use a touch device you can accommodate both methods of input.
How to detect touch device in 2019?
This is really simple with just one line of code:
const touch = matchMedia('(hover: none)').matches;
- What? matchMedia
?
- This is just a JS API to do CSS @media queries. And it is supported in modern browsers: https://caniuse.com/#feat=matchmedia. Of course, you may use such queries directly in CSS:
@media (hover: none){
/* touch stuff goes here */
}
- Ok, what @media queries may be also useful?
@media (hover: none) and (pointer: coarse) {
/* touchscreens */
}
@media (hover: none) and (pointer: fine) {
/* stylus */
}
@media (hover: hover) and (pointer: coarse) {
/* controllers */
}
@media (hover: hover) and (pointer: fine) {
/* mouse or touchpad */
}
But this will query only the primary input method. If you want to go deeper, you may use any-hover
and any-pointer
to query all input devices.
UPD: hack for old browsers removed, seems like most old browsers does not support hover
and pointer
media queries too. You may use touch event detection and touch-only navigator
properties from another answers
UPD2: In your case, it's preferable to use
const touch = matchMedia('(hover: none), (pointer: coarse)').matches;
Detecting touch screen devices with Javascript
+1 for doing hover
and click
both. One other way could be using CSS media queries and using some styles only for smaller screens / mobile devices, which are the ones most likely to have touch / tap functionality. So if you have some specific styles via CSS, and from jQuery you check those elements for the mobile device style properties you could hook into them to write you mobile specific code.
See here: http://www.forabeautifulweb.com/blog/about/hardboiled_css3_media_queries/
Detect click vs. touch in JavaScript
You can use the pointerType
property on PointerEvent
to detect the input type ("mouse"
, "touch"
, or "pen"
):
element.addEventListener('pointerdown', (event) => {
if (event.pointerType === "mouse") {}
if (event.pointerType === "touch") {}
if (event.pointerType === "pen") {}
});
If you want specific events for each type of click, you can create custom events:
const mouse = new Event("mouseclick");
const touch = new Event("touch");
document.addEventListener("pointerdown", ({ pointerType, target }) => {
if (pointerType === "mouse") target.dispatchEvent(mouse);
if (pointerType === "touch") target.dispatchEvent(touch);
});
const someElement = document.querySelector(".box");
someElement.addEventListener("mouseclick", () => {
console.log("Clicked with mouse");
});
someElement.addEventListener("touch", () => {
console.log("Touched with mobile device");
});
someElement.addEventListener("click", () => {
console.log("Clicked by some device (we don't know)");
});
.box {
position: absolute;
inset: 2em;
background: darkred;
padding: 1em;
}
<div class="box">A box with custom events</div>
What's the best way to detect a 'touch screen' device using JavaScript?
Update: Please read blmstr's answer below before pulling a whole feature detection library into your project. Detecting actual touch support is more complex, and Modernizr only covers a basic use case.
Modernizr is a great, lightweight way to do all kinds of feature detection on any site.
It simply adds classes to the html element for each feature.
You can then target those features easily in CSS and JS. For example:
html.touch div {
width: 480px;
}
html.no-touch div {
width: auto;
}
And Javascript (jQuery example):
$('html.touch #popup').hide();
Related Topics
How to Get Image Size (Height & Width) Using JavaScript
Difference Between a Function Call and Function Reference
Group Array Items Using Object
How to Update Nested State Properties in React
Benefits of Using 'Object.Create' For Inheritance
Window.Close and Self.Close Do Not Close the Window in Chrome
Is It an Anti-Pattern to Use Async/Await Inside of a New Promise() Constructor
How May I Reference the Script Tag That Loaded the Currently-Executing Script
Deleting Array Elements in JavaScript - Delete VS Splice
How to Append Something to an Array
Pretty-Print Json Using JavaScript
Selecting Text in an Element (Akin to Highlighting With Your Mouse)
Updating a Nested Array With Mongodb