npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

current-device

v2.6.0

Published

The easiest way to write conditional CSS and/or JavaScript based on device operating system (iOS, Android, Blackberry, Windows, Firefox OS, MeeGo, AppleTV, etc), orientation (Portrait vs. Landscape), and type (Tablet vs. Mobile).

Readme

CURRENT-DEVICE

CI npm version npm downloads

current-device adds CSS classes to <html> for the visitor's operating system, device type and orientation, and gives you the same answers in JavaScript:

<!-- iPhone -->        <html class="ios iphone mobile portrait">
<!-- Galaxy Tab -->    <html class="android tablet landscape">
<!-- MacBook -->       <html class="macos desktop landscape">
import device from "current-device";

device.type; // 'mobile' | 'tablet' | 'desktop' | 'unknown'
device.os; // 'ios' | 'android' | 'windows' | 'macos' | ...
device.orientation; // 'portrait' | 'landscape' | 'unknown'
device.mobile(); // boolean

It is a small (under 3 KB gzipped), dependency-free classifier built for styling, layout conventions and analytics. It reads the user agent string once and sorts the device into a handful of buckets. It does not identify device models, browsers or OS versions, and user agent sniffing has hard limits in 2026: read Limitations before you rely on it.

View the Demo →

Installation

npm install current-device
// ES modules (recommended)
import device from "current-device";

// CommonJS
const device = require("current-device").default;

Importing the module adds the classes to <html> and starts listening for orientation changes. Nothing else is needed. To add the classes with a prefix, or only when you say so, see Custom class prefix.

CDN / Script Tag

<script src="https://unpkg.com/current-device@2/dist/index.global.js"></script>
<script>
  console.log(device.type); // 'mobile', 'tablet' or 'desktop'
</script>

The script defines one global, device. See device.noConflict() if that name is taken.

React

current-device/react has hooks for React 18 and later:

import { useDevice, useOrientation } from "current-device/react";

function Navigation() {
  const { type, os, orientation } = useDevice();
  return type === "mobile" ? <MobileNav /> : <DesktopNav />;
}

function Player() {
  const orientation = useOrientation();
  return <video className={orientation} />;
}

Both re-render the component when the orientation changes.

Server-Side Rendering

current-device can be imported on a server, for example with Next.js, Remix or Astro. A server can't see the device, so there:

  • no classes are added to <html>,
  • every method, such as device.mobile(), returns false,
  • device.type, device.os and device.orientation are 'unknown'.

The React hooks also return 'unknown' on the server and while the page hydrates, and the real values right after. Render something that fits every device for 'unknown'.

In Next.js, components that use the hooks need the "use client" directive.

In a server-rendered app, don't call device methods such as device.mobile() while a component renders. They return false on the server and the real value in the browser, which causes a hydration error, and React then removes the classes from <html>. Use the hooks, or call the methods in an effect or an event handler.

Custom class prefix

The class names current-device adds, such as mobile, desktop and landscape, are generic. In a script that runs on pages you don't own, such as an embedded widget, they can collide with the page's own CSS. For that, import current-device/core instead. It does nothing on import; its createDevice() adds the classes, with the prefix you choose, and starts listening for orientation changes when you call it:

import { createDevice } from "current-device/core";

const device = createDevice({ classPrefix: "cd-" });

device.mobile(); // <html class="cd-ios cd-iphone cd-mobile cd-portrait">

The prefix applies to every class, including cd-landscape/cd-portrait, cd-cordova and cd-node-webkit. Without classPrefix, createDevice() adds the same classes as the main entry point.

The returned object has the whole JavaScript API, but:

  • it is not assigned to the device global, so noConflict() does nothing but return it;
  • each createDevice() call adds its own classes and listener, so call it once;
  • the user agent is read when createDevice() is called, not when the module is imported, which also makes detection easy to unit-test with different user agents.

Without a DOM, createDevice() returns a device whose methods return false and whose properties are 'unknown', like the main entry point. The options type is exported as DeviceOptions.

TypeScript

The package ships its own types:

import device from "current-device";
import type { Device, DeviceType, DeviceOs, DeviceOrientation } from "current-device";

const os: DeviceOs = device.os;
const type: DeviceType = device.type;
const isPhone: boolean = device.mobile();

CSS Classes

One operating-system class and one type class are added to <html>, plus the orientation class.

Two more classes describe the runtime rather than the device:

Orientation

The orientation class is the only one that changes while the page is open. On phones and tablets it follows the screen's orientation; on desktops, where the screen doesn't rotate, it follows the window's aspect ratio, so a portrait monitor or a tall window is portrait. A square window is portrait, like the CSS (orientation: portrait) media query.

JavaScript API

Type

Exactly one of the three is true in a browser.

Operating System and Device

Runtime

Orientation

const unsubscribe = device.onChangeOrientation((newOrientation: "landscape" | "portrait") => {
  console.log(`New orientation is ${newOrientation}`);
});

unsubscribe(); // removes the callback again

Properties

The properties hold the first match, so you don't have to call the methods one by one.

Notes on device.os:

  • It is 'ios' for every iPhone, iPad and iPod touch. The DeviceOs type also lists 'iphone', 'ipad' and 'ipod' for backwards compatibility, but device.os never has those values; use device.iphone(), device.ipad() and device.ipod() instead. The three values will be removed from the type in 3.0.
  • Where two checks match, the more specific platform wins: a HarmonyOS device is 'harmonyos' (and device.android() is also true on the Android-based versions), an Android app running on a Chromebook is 'chromeos', and an Android TV is 'android' with device.television() true. 'television' is used for TVs whose operating system isn't recognised (Tizen, webOS, Roku...).
  • Feature phones and phones on platforms without their own method are 'unknown' with device.type === 'mobile'.

device.type and device.os are computed once, when the module is imported (or createDevice() is called); only device.orientation changes afterwards.

device.noConflict()

Returns the device object and gives the global device variable back to its previous owner. Only relevant for the <script> build.

const currentDevice: Device = device.noConflict();

Device Support

Current platforms:

  • iOS and iPadOS: iPhone, iPad, iPod touch
  • macOS
  • Android: phones, tablets and TVs
  • HarmonyOS, including HarmonyOS NEXT (OpenHarmony): phones, tablets and PCs
  • ChromeOS, including Android apps running on a Chromebook
  • Windows: desktops, laptops and 2-in-1s (desktop), Windows RT tablets, Windows Phone and Windows Mobile
  • Linux desktops
  • Televisions and set-top boxes: Android TV, Google TV, Fire TV, Chromecast, Samsung Tizen, LG webOS, Roku, Apple TV, HbbTV, Vizio, Hisense VIDAA, Opera TV
  • Feature phones and other handsets (Java ME, Symbian, KaiOS, Tizen, Sailfish, Palm webOS...) as mobile

Legacy platforms, still recognised by user agent although their browsers cannot run the ES2015 bundle (see Browser Support): BlackBerry and the PlayBook, Windows Phone, Firefox OS and MeeGo. Their methods stay in 2.x for compatibility.

Browser Support

current-device 2.x ships ES2015 JavaScript without polyfills. It runs in any browser with full ES2015 support:

| Browser | Minimum version | | --- | --- | | Chrome, Android WebView | 51 | | Edge | 15 | | Firefox | 54 | | Safari (macOS and iOS) | 10 | | Samsung Internet | 5 | | Opera | 38 |

Internet Explorer and other browsers without ES2015 support are not supported. This includes the built-in browsers of several platforms that current-device still recognizes by user agent: the Android stock browser (Android 4.4 and earlier), BlackBerry, Windows Phone 8.x, Firefox OS and MeeGo. If you need to support them, use current-device 0.10.x, which ships ES5:

<script src="https://unpkg.com/[email protected]/umd/current-device.min.js"></script>

Limitations

current-device classifies the user agent string, once, at import. That is enough to tell phones, tablets and desktops apart and to name the operating system for the vast majority of visitors (89% of the 35,000 user agents in the Matomo device-detector fixtures get the right type). It is not device identification, and these limits are inherent to the approach:

  • Results don't follow the window. device.type, device.os and their classes describe the device and are computed once. Resizing the browser, docking a tablet or opening the page in a split screen only updates the orientation. Use CSS media queries for layout that should follow the viewport.
  • Chrome's reduced user agent. Since Chrome 110 every Android Chrome user agent says Android 10; K, without the device model. Phone versus tablet then rests on Chrome's own Mobile token, which Chrome adds on screens narrower than 600dp, so a 7" or 8" tablet is a phone. Tablet model names still help in browsers that send them (WebViews, Samsung Internet, Huawei Browser): Galaxy Tab, Lenovo Tab, MediaPad/MatePad, Huawei -W09 models, Kindle Fire and a few others are tablets even with Mobile.
  • Apple's Mac user agent. iPadOS 13+ and an iPhone with "Request Desktop Website" both send the Mac Safari user agent. current-device recognises them by their touchscreen (navigator.maxTouchPoints) and tells the iPhone from the iPad by screen size. This relies on navigator.platform, which browsers have deprecated; if Safari stops reporting it, desktop-mode iPads become Macs.
  • Windows and ChromeOS tablets are desktops. No modern browser on Windows or ChromeOS puts a tablet hint in the user agent, so a Surface, a 2-in-1 or a Chromebook tablet is desktop. Only Windows RT devices, whose Internet Explorer said ARM and Touch, are windows tablet.
  • Client Hints are not used. Detection is user agent only; navigator.userAgentData is Chromium-only and its useful fields are asynchronous, which doesn't fit classes that must be set at import time.
  • Foldables. Unfolded, a foldable's screen is wider than 600dp and Chrome drops Mobile. Galaxy Z Fold and Pixel Fold are phones in either state; other foldables are tablets when unfolded.
  • Televisions have type: 'desktop' with the television class, and an Android TV has os: 'android'; there is no television type. Wearables, game consoles, car displays, smart displays and VR headsets have no category of their own and land in mobile or desktop.
  • A phone whose model name contains "TV" as a separate word (for example "KAZAM TV 45") is detected as a television.
  • KaiOS keeps the Firefox OS user agent it descends from, so it is reported as fxos, not as a separate platform.
  • No browsers, versions or models. current-device does not report the browser, the OS version or the device model. For those, use a full parser such as ua-parser-js or device-detector.

Best Practices

Use current-device for what only the platform can tell you: interaction conventions (Android and iOS users expect different controls), app-store links, platform-specific help text, and analytics segments.

Don't use it as a proxy for capabilities or screen size. The browser can tell you those directly, on every device, and keeps them up to date:

  • layout that depends on the viewport: CSS media queries, or matchMedia()
  • touch versus mouse: (pointer: coarse) and (hover: none) media queries
  • orientation-dependent layout: the (orientation: portrait) media query
  • an API or feature: check for the feature itself

In short, check for features when you need features, and check for the platform when you need the platform.

Contributors

Thanks goes to these wonderful people (emoji key):

This project follows the all-contributors specification. Contributions of any kind welcome!