Is detecting mobile devices with JavaScript all bad?

A tweet about using JavaScript to detect a mobile device from Niels Leenheer (a.k.a. Mr. html5test) got me thinking. Because he says you should never use JavaScript to distinguish between mobile and desktop/laptop. A good reason to ignore this distinction is: What does “mobile” even mean? A cell phone? A tablet? A watch? Any device with a small screen? Like most things in web development: it depends.

The definition of mobile has faded rapidly the past couple of years. First came tablets that were a category between a mobile phone and a notebook. Most developers tended to considered them mobile. But not always. Large phones became a trend, that filled the gap between phones and tablets, so called phablets. But then Microsoft came with the Surface, which is a notebook that can be used as a tablet (although Windows tablets existed before that). And Apple with the iPad Pro, a tablet that can be used like a laptop. Even some phones can now be used as a desktop computer, for example with Microsoft Continuum or Samsung DeX (this does not seem to get a lot of traction). Also there are TV sticks that run Android. So a mobile OS does not automatically mean it is a mobile device. And desktop browsers have developer tools that can emulate mobile browsers.

So, yes. It’s complicated as PPK likes to say.

A use case for detecting mobile devices I see is autoplaying videos. Well, maybe that is not a valid use case for everyone. Some even say video backgrounds suck (pardon my French).

An important reason to detect mobile devices is to avoid waisting large amounts of data. Mobile data plans are still quite expensive and most plans come with a monthly data limit. To get an impression you can use What does my site cost? to see costs for different countries, also related to income.

Of course there are a couple of assumptions if you want to use mobile detection.

Mobile devices use a mobile network

Well actually, you also can use WiFi on smartphones. People tend to use their mobile phone the most at home, connected to WiFi. Unfortunately, you cannot really detect the speed of a connection before a page is loaded. There is the Network Information API, but it doesn’t work in all browsers. Even if you have a fast connection like LTE, there is no guarantee the full bandwidth is available. And latency is also a problem on mobile networks.

Desktop/Laptop computers use broadband networks

Desktop computers and notebooks usually use a wired connection or WiFi that connects to DSL / Cable / a dedicated network. But not everyone has access to broadband. In rural areas some people still have to use an analog modem with a 56 kbit/s connection speed. That is slower than most mobile networks.

Some laptops have a SIM card slot to connect to a mobile network. And also you can connect to a mobile phone through tethering. But a lot of desktop browsers do not support the Network Information API, so detecting this is unreliable.

Mobile detection solution

My recipe for mobile detection consist of:

  • If the browser says it is mobile I believe it.
  • Has a small screen.
  • Uses a mobile network.

It is a compromise with all the caveats mentioned above. So here is an example you could use to load an autoplaying video, but only on desktop. The video attributes “autoplay loop muted playsinline” are used to comply with restrictions by browser vendors to trigger autoplay. But users can switch them off completely. Using a poster image will ensure they will at least see that. Oh, and I added a noscript tag, because I’m hardcore old school.


<div id="hero">
<noscript><img src="hero-image.jpg" alt=""></noscript>
</div>

<script>
function isMobile() {
  if (navigator.userAgent.match(/Mobi/)) {
    return true;
  }
  
  if ('screen' in window && window.screen.width < 1366) {
    return true;
  }

  var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
  if (connection && connection.type === 'cellular') {
    return true;
  }

  return false;
}

(function () {
  var hero = document.getElementById('hero');
  var mobile = isMobile();
  if (mobile) {
    hero.innerHTML = '<img src="hero-image.jpg" alt="">';
  } else {
    hero.innerHTML = '<video src="hero-image.mp4" poster="hero-image.jpg" autoplay loop muted playsinline>';
  }
})();
</script>

Actually, you can also use Gif/aPNG/WebP image formats or even use video as an image in Safari. But I'd rather not go into that.

What I would like to add is a word about accessibility. Autoplaying can be problematic with some users that are sensitive to motion. They can set a preference to reduce motion. Currently it is only supported on Apple devices. It will probably be part of CSS5. So below is an improved example to load an autoplaying video by adding window.matchMedia('(prefers-reduced-motion: reduce)'). But this has nothing to do with mobile detection, just a better user experience.


<div id="hero">
<noscript><img src="hero-image.jpg" alt=""></noscript>
</div>

<script>
function prefersReducedMotion() {
  if (!'matchMedia' in window) {
    return false;
  }

  var motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
  if (!motionQuery.matches) {
    return false;
  }

  return true;
}

function isMobile() {
  if (navigator.userAgent.match(/Mobi/)) {
    return true;
  }
  
  if ('screen' in window && window.screen.width < 1366) {
    return true;
  }

  var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
  if (connection && connection.type === 'cellular') {
    return true;
  }

  return false;
}

(function () {
  var hero = document.getElementById('hero');
  var mobile = isMobile();
  var reduceMotion = prefersReducedMotion();
  if (!mobile && !reduceMotion) {
    hero.innerHTML = '<video src="hero-image.mp4" poster="hero-image.jpg" autoplay loop muted playsinline>';
  } else {
    hero.innerHTML = '<img src="hero-image.jpg" alt="">';
  }
})();
</script>

So is detecting mobile devices with JavaScript all bad? Mostly, but it can be useful under some circumstances. And it would make certain clients happy. You just need to be aware of the limitations and implications.