Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use WordPress’s body_class filter to append controlled browser or operating-system class names, and confirm that your theme prints them with body_class(). Keep the original class array intact. Browser and OS detection based on request headers is best effort; use CSS media queries for responsive, viewport-based layout.

1. Confirm that the theme outputs WordPress body classes

Open the theme template that renders the document body, commonly header.php, and look for:

<body <?php body_class(); ?>>

body_class() prints the body element’s class attribute and accepts additional class names as a string or array. See the WordPress body_class() reference. If the theme does not call it, classes added through the filter will not appear in the HTML.

2. Add classes with the body_class filter

Put site-specific code in a small custom plugin when possible, or in the active theme’s functions.php. The callback receives the existing classes, appends your additions, and returns the array:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
add_filter( 'body_class', 'site_add_client_classes' );

function site_add_client_classes( $classes ) {
    $classes[] = 'client-category';

    return $classes;
}

Do not replace $classes with a new array. Returning the original array preserves WordPress’s page, post, template, and theme classes. The filter contract is documented in the body_class hook reference.

3. Detect a browser and operating system

The following example uses the request’s user-agent string to choose from a fixed set of class slugs. It checks more-specific browser tokens before broader ones, then appends only known values. User-agent identification can be missing, changed, or spoofed, so treat the result as a hint rather than a security boundary.

add_filter( 'body_class', 'site_add_client_classes' );

function site_add_client_classes( $classes ) {
    $ua = isset( $_SERVER['HTTP_USER_AGENT'] )
        ? strtolower( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) )
        : '';

    // Browser: test Edge before Chrome, and Chrome before Safari.
    if ( strpos( $ua, 'edg/' ) !== false ) {
        $classes[] = 'browser-edge';
    } elseif ( strpos( $ua, 'firefox/' ) !== false ) {
        $classes[] = 'browser-firefox';
    } elseif ( strpos( $ua, 'opr/' ) !== false || strpos( $ua, 'opera' ) !== false ) {
        $classes[] = 'browser-opera';
    } elseif ( strpos( $ua, 'chrome/' ) !== false || strpos( $ua, 'crios/' ) !== false ) {
        $classes[] = 'browser-chrome';
    } elseif ( strpos( $ua, 'safari/' ) !== false ) {
        $classes[] = 'browser-safari';
    }

    // Operating system: test Android before Linux because Android strings often include Linux.
    if ( strpos( $ua, 'android' ) !== false ) {
        $classes[] = 'os-android';
    } elseif ( strpos( $ua, 'iphone' ) !== false || strpos( $ua, 'ipad' ) !== false || strpos( $ua, 'ipod' ) !== false ) {
        $classes[] = 'os-ios';
    } elseif ( strpos( $ua, 'windows' ) !== false ) {
        $classes[] = 'os-windows';
    } elseif ( strpos( $ua, 'mac os x' ) !== false || strpos( $ua, 'macintosh' ) !== false ) {
        $classes[] = 'os-macos';
    } elseif ( strpos( $ua, 'linux' ) !== false ) {
        $classes[] = 'os-linux';
    }

    return $classes;
}

This produces classes such as browser-firefox os-linux alongside WordPress’s normal classes. Keep the values in the code fixed; never copy arbitrary header content directly into a class name.

WordPress also documents browser-detection globals and advises using suitable API functions where available in its Common APIs handbook. If your project already relies on those documented values, map them to the same controlled slugs instead of maintaining a second parser.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

4. Use the right mechanism for the job

Need Best mechanism What it tells you Main limitation
Responsive layout or viewport-width styling CSS media queries Available viewport characteristics Does not identify a browser or operating system
Browser-specific or OS-specific server markup body_class plus a detection signal A best-effort request category User-agent signals may be absent, altered, or misleading
Mobile-device branching wp_is_mobile() A mobile/non-mobile classification It is not a browser-name, OS, or screen-width detector

Do not use browser or OS classes to solve a CSS responsiveness problem. WordPress states that wp_is_mobile() detects mobile-device status, not display width, and may classify tablets as mobile; it is not a replacement for media queries. See the wp_is_mobile() reference.

5. If you only need a mobile class

For a genuine server-side mobile/non-mobile branch, use the core function rather than parsing the user agent yourself:

add_filter( 'body_class', 'site_add_mobile_class' );

function site_add_mobile_class( $classes ) {
    $classes[] = wp_is_mobile() ? 'device-mobile' : 'device-not-mobile';

    return $classes;
}

Current WordPress documentation says the function checks the Sec-CH-UA-Mobile request header when available and otherwise checks selected user-agent substrings. Its result is still a device classification, not a measurement of CSS viewport width.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

6. Account for page caching

If the rendered HTML changes because of wp_is_mobile() or another request-based classification, the cache must maintain separate mobile and non-mobile variants. Otherwise, a response generated for one category can be served to the other category. Verify that every page-cache layer, full-page cache, CDN, and reverse proxy varies the cache key correctly before enabling device-dependent markup. WordPress calls out this requirement in the wp_is_mobile() documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Browser- and OS-specific classes create the same practical concern whenever they alter server-rendered output: either configure the cache to vary safely on the relevant request signal or keep the variation in client-side CSS or JavaScript.

7. Verify the result

  1. Clear PHP opcode, page, CDN, and browser caches after deploying the code.
  2. View the rendered page source or inspect the <body> element in developer tools.
  3. Confirm that the expected fixed slugs appear and that WordPress’s existing classes remain present.
  4. Test representative browsers and operating systems, including an unknown or privacy-reduced user agent.
  5. If device-dependent markup is enabled, request the page through each cache path and confirm that one category’s HTML is not reused for another.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.