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(); // booleanIt 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.
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.
<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.
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} />;
}useDevice()returns{ type, os, orientation }, with the same values asdevice.type,device.osanddevice.orientation.useOrientation()returns only the orientation.
Both re-render the component when the orientation changes.
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(), returnsfalse, device.type,device.osanddevice.orientationare'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.
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();One operating-system class and one type class are added to <html>, plus the
orientation class.
| Device | CSS Classes |
|---|---|
| iPhone | ios iphone mobile |
| iPad (also iPadOS 13+ with its Mac user agent) | ios ipad tablet |
| iPod touch | ios ipod mobile |
| Mac | macos desktop |
| Android phone | android mobile |
| Android tablet | android tablet |
| Android TV, Google TV, Fire TV, Chromecast | android television |
| HarmonyOS phone | harmonyos mobile |
| HarmonyOS tablet | harmonyos tablet |
| HarmonyOS PC | harmonyos desktop |
| ChromeOS (also an Android app on a Chromebook) | chromeos desktop |
| Windows desktop, laptop or 2-in-1 | windows desktop |
| Windows RT tablet | windows tablet |
| Windows Phone, Windows Mobile | windows mobile |
| Linux desktop | linux desktop |
| Other television or set-top box (Tizen, webOS, Roku, Apple TV, HbbTV...) | television |
| BlackBerry phone | blackberry mobile |
| BlackBerry PlayBook | blackberry tablet |
| Firefox OS or KaiOS phone | fxos mobile |
| Firefox OS tablet | fxos tablet |
| MeeGo | meego mobile |
| Other phone (feature phone, Symbian, Tizen, Sailfish...) | mobile |
| Anything else | desktop |
Two more classes describe the runtime rather than the device:
| Runtime | CSS Class |
|---|---|
Cordova app (window.cordova exists and the page is loaded from file:) |
cordova, added to the classes above |
NW.js or Electron renderer (window.process exists) |
node-webkit. On Windows and macOS the classes above win; on Linux it is added instead of them |
| Orientation | CSS Class |
|---|---|
| Landscape | landscape |
| Portrait | portrait |
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.
| Type | Method |
|---|---|
| Phone | device.mobile() |
| Tablet | device.tablet() |
| Neither: desktops, laptops and televisions | device.desktop() |
Exactly one of the three is true in a browser.
| Device | Method |
|---|---|
| iOS or iPadOS | device.ios() |
| iPhone | device.iphone() |
| iPad | device.ipad() |
| iPod touch | device.ipod() |
| Mac | device.macos() |
| Android (phones, tablets, TVs, HarmonyOS, Android apps on a Chromebook) | device.android() |
| Android phone | device.androidPhone() |
| Android tablet | device.androidTablet() |
HarmonyOS, including HarmonyOS NEXT (the Android-based versions are also android()) |
device.harmonyos() |
| ChromeOS | device.chromeos() |
| Windows | device.windows() |
| Windows Phone, Windows Mobile | device.windowsPhone() |
| Windows RT tablet | device.windowsTablet() |
| Linux desktop | device.linux() |
| Television or set-top box (any OS) | device.television() |
| BlackBerry | device.blackberry() |
| BlackBerry phone | device.blackberryPhone() |
| BlackBerry PlayBook | device.blackberryTablet() |
| Firefox OS or KaiOS | device.fxos() |
| Firefox OS or KaiOS phone | device.fxosPhone() |
| Firefox OS tablet | device.fxosTablet() |
| MeeGo | device.meego() |
| Runtime | Method |
|---|---|
| Cordova app | device.cordova() |
| NW.js or Electron renderer | device.nodeWebkit() |
| Orientation | Method |
|---|---|
| Landscape | device.landscape() |
| Portrait | device.portrait() |
const unsubscribe = device.onChangeOrientation((newOrientation: "landscape" | "portrait") => {
console.log(`New orientation is ${newOrientation}`);
});
unsubscribe(); // removes the callback againThe properties hold the first match, so you don't have to call the methods one by one.
| Property | Type | Value |
|---|---|---|
| device.type | DeviceType | 'mobile', 'tablet', 'desktop' or 'unknown' |
| device.os | DeviceOs | 'ios', 'android', 'harmonyos', 'chromeos', 'windows', 'macos', 'linux', 'television', 'blackberry', 'fxos', 'meego' or 'unknown' |
| device.orientation | DeviceOrientation | 'landscape', 'portrait' or 'unknown' |
Notes on device.os:
- It is
'ios'for every iPhone, iPad and iPod touch. TheDeviceOstype also lists'iphone','ipad'and'ipod'for backwards compatibility, butdevice.osnever has those values; usedevice.iphone(),device.ipad()anddevice.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'(anddevice.android()is also true on the Android-based versions), an Android app running on a Chromebook is'chromeos', and an Android TV is'android'withdevice.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'withdevice.type === 'mobile'.
device.type and device.os are computed once when the module is imported;
only device.orientation changes afterwards.
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();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.
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/current-device@0.10.2/umd/current-device.min.js"></script>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.osand 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 ownMobiletoken, 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-W09models, Kindle Fire and a few others are tablets even withMobile. - 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 onnavigator.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 saidARMandTouch, arewindows tablet. - Client Hints are not used. Detection is user agent only;
navigator.userAgentDatais 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 thetelevisionclass, and an Android TV hasos: 'android'; there is no television type. Wearables, game consoles, car displays, smart displays and VR headsets have no category of their own and land inmobileordesktop. - 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.
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.
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!