Question
Detect Mobile-Friendly Capabilities with jQuery and JavaScript
Question
Is there a way to determine whether a visitor is using a mobile device with jQuery, similar to a CSS @media query? I want to run different JavaScript when the browser is being used on a handheld device. The deprecated jQuery $.browser feature does not meet this need.
Short Answer
jQuery does not provide a reliable way to identify a “mobile device.” Instead of guessing the device from its name or browser string, detect the capability your code actually needs, such as a narrow layout, touch-friendly pointer, hover support, or a specific browser API. You can use CSS media queries for presentation and JavaScript’s matchMedia() when behavior must change.
Concept
A device is not the same thing as a screen size or an input method. For example:
- A tablet may have a large screen but be operated by touch.
- A laptop may have a touchscreen and a mouse.
- A desktop browser window can be resized to phone width.
- A phone can connect to a mouse, keyboard, or external display.
Because of these combinations, there is no dependable yes-or-no test for “is mobile” that produces the right result for every visitor. jQuery is a DOM utility library; it does not have special knowledge of the physical device.
Use capability detection instead. Ask a focused question that matches the behavior you are about to implement:
- Use CSS media queries when only the layout or appearance changes.
- Use
matchMedia()when JavaScript must react to a media query. - Use
(pointer: coarse)when controls should support less precise pointing, often touch. - Use
(hover: hover)when an interaction depends on hover. - Check whether a required API exists before using it.
This approach keeps an application usable on new devices and hybrid devices, rather than maintaining a fragile list of user-agent names.
Mental Model
Think of device detection as trying to identify a person by guessing from their coat. It may work sometimes, but it can easily be wrong.
Capability detection is like asking what the person can do right now:
- Can they hover a pointer over something?
- Is their pointing device broad and less precise?
- Is the available screen area narrow?
Your program should choose the right interaction based on those answers, not on a label such as “phone,” “tablet,” or “desktop.”
Syntax and Examples
Use CSS for visual differences whenever possible:
/* Base styles work everywhere. */
.menu-button {
display: block;
}
/* A wider layout can display the full navigation. */
@media (min-width: 48rem) {
.menu-button {
display: none;
}
}
When JavaScript needs the same type of condition, create a media-query list with window.matchMedia():
const compactLayout = window.matchMedia("(max-width: 47.99rem)");
if (compactLayout.matches) {
console.log("Use compact-layout behavior.");
} else {
console.log("Use wide-layout behavior.");
}
compactLayout.matches is true while the viewport matches the query. It means the available viewport is narrow; it does not prove that the visitor has a phone.
For an interaction that needs larger, touch-friendly controls, test the primary pointer:
Step by Step Execution
Consider a navigation menu that must use click-to-open behavior in compact layouts.
const compactLayout = window.matchMedia("(max-width: 47.99rem)");
function updateMenuBehavior(event) {
if (event.matches) {
$(".site-menu").addClass("site-menu--compact");
} else {
$(".site-menu").removeClass("site-menu--compact");
}
}
updateMenuBehavior(compactLayout);
compactLayout.addEventListener("change", updateMenuBehavior);
Step by step:
matchMedia("(max-width: 47.99rem)")creates aMediaQueryListfor the viewport-width rule.compactLayout.matchesistrueif the viewport is currently no wider than47.99rem.updateMenuBehavior(compactLayout)runs immediately, so the page is correct on first load.- If the query matches, jQuery adds the
site-menu--compactclass.
Real World Use Cases
- Responsive navigation: Show a menu toggle in compact widths and a full navigation bar in wider widths.
- Hover-only previews: Enable image previews on pointer hover only when the user can hover.
- Touch-friendly controls: Increase spacing around small controls when a coarse pointer is primary.
- Maps and dashboards: Avoid loading an optional, expensive visualization until there is enough viewport space.
- Drag-and-drop alternatives: Provide buttons such as “Move up” and “Move down” when a drag interaction would be difficult with touch.
- Progressive enhancement: Check for browser features such as geolocation, notifications, or
IntersectionObserverbefore enabling an optional feature.
Real Codebase Usage
In production code, developers usually define behavior in terms of requirements rather than device categories.
Keep presentation in CSS
Use CSS media queries for layout, visibility, spacing, and typography. This avoids duplicating styling rules in JavaScript.
Use JavaScript only for behavior
A common pattern is to create one named media-query object and subscribe to its changes:
const canHover = window.matchMedia("(hover: hover)");
function configureTooltips({ matches }) {
if (!matches) {
$("[data-tooltip]").off("mouseenter mouseleave");
return;
}
$("[data-tooltip]")
.off("mouseenter mouseleave")
.on("mouseenter", function () {
$(this).addClass("has-tooltip-open");
})
.on("mouseleave", function () {
$(this).removeClass("has-tooltip-open");
});
}
configureTooltips(canHover);
canHover.addEventListener(, configureTooltips);
Common Mistakes
Using a user-agent regular expression as the main solution
// Fragile: device names change, strings can be spoofed, and hybrid devices exist.
const isMobile = /Android|iPhone|iPad/i.test(navigator.userAgent);
This guesses a device category rather than checking what the browser can do. Prefer matchMedia() for layout and input capabilities.
Treating a narrow viewport as proof of a phone
const isMobile = window.innerWidth < 768;
A narrow browser window can be on a desktop, and a phone may have a wide viewport in landscape or on an external display. Name this value by what it means instead:
const isCompactLayout = window.matchMedia("(max-width: 767px)").matches;
Detecting touch with "ontouchstart" in window
const isTouchDevice = "ontouchstart" in window;
Comparisons
| Approach | What it answers | Best use | Limitation |
|---|---|---|---|
CSS @media | Does the current presentation condition match? | Layout, spacing, visibility | CSS only; it does not directly run JavaScript |
window.matchMedia() | Does a media query currently match? | JavaScript behavior tied to viewport, hover, or pointer capabilities | Does not identify a physical device |
(pointer: coarse) | Is the primary pointer relatively imprecise? | Larger targets and touch-friendly interactions | Some touch-capable devices use a fine primary pointer |
(hover: hover) | Can the primary input hover? | Hover previews and hover menus | Do not use it as the only access method for important content |
Cheat Sheet
// Is the viewport currently compact?
const compact = window.matchMedia("(max-width: 47.99rem)");
if (compact.matches) {
// Compact-layout behavior
}
// React when that condition changes.
compact.addEventListener("change", (event) => {
console.log(event.matches);
});
// Is the primary pointer coarse, often touch-oriented?
const coarsePointer = window.matchMedia("(pointer: coarse)").matches;
// Can the primary input hover?
const canHover = window.matchMedia("(hover: hover)").matches;
// Check a specific API before using it.
if ("geolocation" in navigator) {
// Geolocation is available.
}
- jQuery has no reliable built-in “is mobile” test.
- Prefer CSS
@mediaqueries for visual changes. matchesis a boolean result for the query .
FAQ
Can jQuery detect whether a user is on a mobile device?
No reliable jQuery method can identify every mobile device correctly. jQuery can work with the result of JavaScript capability checks, but it does not provide a dependable mobile-device classification.
What should I use instead of $.browser?
Use CSS media queries for styling and window.matchMedia() for JavaScript behavior. Check browser APIs directly when you need a particular feature.
How do I check for a mobile-sized screen in JavaScript?
Use window.matchMedia("(max-width: 47.99rem)").matches. Call the result something like isCompactLayout, because it describes viewport width rather than the physical device.
Is (pointer: coarse) the same as detecting touch?
Not exactly. It indicates that the primary pointer is relatively imprecise, which is common on touch devices. A computer can support touch while still having a fine mouse pointer as primary input.
Should I use navigator.userAgent to detect iPhone or Android?
Avoid it for normal layout and interaction decisions. User-agent strings are not a reliable capability signal and can be modified or reduced. Use it only for a narrowly justified platform-specific workaround.
Why should I listen for matchMedia changes?
The viewport and input context can change after page load, such as when a device rotates or a desktop window is resized. The change event lets your behavior stay in sync.
Mini Project
Description
Build a responsive product-card interaction. On devices that support hover, moving the pointer over a card reveals its details. On non-hover devices, each card has a button that reveals the same details. The project demonstrates capability detection while keeping the essential action available to every user.
Goal
Create product cards whose details can be revealed with hover when available and with a button on every device.
Requirements
Requirement 1
Keep learning
Related questions
Abort Ajax Requests with jQuery jqXHR.abort()
Learn how to cancel an in-progress jQuery Ajax request with jqXHR.abort(), handle abort status safely, and avoid stale UI updates.
Access the Correct this Inside a JavaScript Callback
Learn why JavaScript this changes in callbacks and how to preserve an object context using bind, arrow functions, and event handler patterns.
Add Key-Value Pairs to JavaScript Objects
Learn how to add key-value pairs to JavaScript objects with dot and bracket notation, dynamic keys, examples, and common mistakes.