Home >Web Front-end >CSS Tutorial >How to detect touch devices using browser media queries

How to detect touch devices using browser media queries

Barbara Streisand
Barbara StreisandOriginal
2025-01-20 18:10:121018browse

This article explores reliable methods for detecting user input devices (touch, mouse, stylus) in web development, moving beyond unreliable techniques like screen size checks or user-agent sniffing. The focus is on leveraging CSS Media Queries, specifically pointer, hover, and any-pointer, for accurate device capability detection. These queries provide precise information about input modalities, leading to more accessible and responsive web applications.

While simpler approaches might seem convenient, they often yield inaccurate results. For instance, a user connecting a mouse to a smartphone invalidates size-based assumptions. CSS Media Queries offer a superior solution, providing precise data based on actual device characteristics.

CSS Media Queries: A Reliable Approach

This article delves into pointer and hover Media Queries, demonstrating their implementation as React hooks.

pointer Media Query

The pointer Media Query determines the presence and precision of a pointing device. It returns one of three values:

  • none: No pointing device available (e.g., voice-controlled devices).
  • coarse: A pointing device is present but lacks precision (e.g., finger on a touchscreen).
  • fine: A highly precise pointing device is available (e.g., mouse).

The window.matchMedia method provides convenient access to Media Query results within code.

useMatchMedia Hook

To avoid code redundancy, a custom useMatchMedia hook is created to retrieve and track Media Query results. This hook utilizes window.matchMedia and adds an event listener to detect changes in the query's match status. A cleanup function ensures the listener is removed when the component unmounts or the query changes.

<code class="language-typescript">export const useMatchMedia = (query: string) => {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    const media = window.matchMedia(query);
    if (media.matches !== matches) {
      setMatches(media.matches);
    }
    const listener = () => setMatches(media.matches);
    media.addEventListener('change', listener);
    return () => media.removeEventListener('change', listener);
  }, [matches, query]);

  return matches;
};</code>

Detecting Primary Pointer Capabilities

The usePrimaryPointerQuery hook determines the primary pointer type. It calls useMatchMedia with queries for none, coarse, and fine pointer types, returning the appropriate value from a Pointers enum.

<code class="language-typescript">import { useMatchMedia } from './useMatchMedia.ts';
import { Pointers } from './types.ts';

export const usePrimaryPointerQuery = () => {
  const isNone = useMatchMedia('(pointer: none)');
  const isCoarse = useMatchMedia('(pointer: coarse)');
  const isFine = useMatchMedia('(pointer: fine)');
  if (isNone) {
    return Pointers.none;
  } else if (isCoarse) {
    return Pointers.coarse;
  } else if (isFine) {
    return Pointers.fine;
  }
};</code>

How to detect touch devices using browser media queries

Detecting Additional Pointer Capabilities

While only one primary pointer exists, devices can have secondary pointers (e.g., Bluetooth keyboard, joystick). The any-pointer Media Query checks the precision of any available pointer. The useAnyPointerQuery hook accepts a pointer type and uses useMatchMedia with a dynamically generated query string.

<code class="language-typescript">export const useMatchMedia = (query: string) => {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    const media = window.matchMedia(query);
    if (media.matches !== matches) {
      setMatches(media.matches);
    }
    const listener = () => setMatches(media.matches);
    media.addEventListener('change', listener);
    return () => media.removeEventListener('change', listener);
  }, [matches, query]);

  return matches;
};</code>

How to detect touch devices using browser media queries

Working Demo

A complete demo showcasing the hooks is available:

Advanced Detection: hover and any-hover

hover and any-hover Media Queries further refine detection by checking for hover capabilities. Combining these with pointer queries allows for more precise device identification.

Pointer value Hover value Device
coarse none Modern touch screens
fine none Stylus-based devices
coarse hover Joystick or TV remote
fine hover Mouse

For example, detecting a stylus as the primary input:

<code class="language-typescript">import { useMatchMedia } from './useMatchMedia.ts';
import { Pointers } from './types.ts';

export const usePrimaryPointerQuery = () => {
  const isNone = useMatchMedia('(pointer: none)');
  const isCoarse = useMatchMedia('(pointer: coarse)');
  const isFine = useMatchMedia('(pointer: fine)');
  if (isNone) {
    return Pointers.none;
  } else if (isCoarse) {
    return Pointers.coarse;
  } else if (isFine) {
    return Pointers.fine;
  }
};</code>

This approach ensures more robust and accurate detection of user input devices, leading to better user experience and accessibility.

The above is the detailed content of How to detect touch devices using browser media queries. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn