ScreenshotNeo

BlogHow-to

How to Use Modernizr for Browser Feature Detection

Detect browser capabilities with Modernizr, use results in JavaScript and CSS, and write custom tests with practical fallbacks.

By the ScreenshotNeo team4 October 20267 min read

Modernizr detects whether a browser supports specific web capabilities so your code can choose an appropriate experience. Read a result such as Modernizr.canvas in JavaScript, or use the generated .canvas and .no-canvas classes in CSS. Detect the capability your feature depends on instead of guessing from the browser name.

1. Add Modernizr to your project

Build or download a Modernizr script containing the feature detects your project needs, then load it before code or styles that depend on its results. The official Modernizr documentation describes feature detects, configuration, and its API. Avoid assuming a particular current release or maintenance status; confirm the version and build your project uses.

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <script src="/assets/modernizr-custom.js"></script>
  <link rel="stylesheet" href="/assets/site.css">
</head>
<body>
  <main>Content works without the enhancement.</main>
  <script src="/assets/app.js" defer></script>
</body>
</html>

Replace /assets/modernizr-custom.js with the build you generated. Include only tests the application uses to keep the script focused. Loading the script in the document head lets it add classes before the page is rendered, reducing visible style changes. If you load it later or asynchronously, ensure dependent code waits until the script has run.

2. Branch in JavaScript

Modernizr exposes feature results as boolean properties. A built-in test might be Modernizr.canvas; use the property for the feature your application relies on.

const canvas = document.createElement('canvas');

if (Modernizr.canvas) {
  // Use the canvas-based experience.
  startCanvasExperience(canvas);
} else {
  // Keep the content usable without canvas.
  showStaticVisualization();
}

The example assumes startCanvasExperience and showStaticVisualization are functions in your application. A detection result tells you what the test found, not what fallback content your product should provide. Keep core content and actions available where possible.

3. Use generated classes in CSS

By default, Modernizr adds classes for detected features to the root HTML element. A supported test gets a class such as canvas; an unsupported test gets the corresponding no- class, such as no-canvas.

/* Baseline experience remains available. */
.visualization {
  background: #f3f5f7;
  color: #20252b;
}

/* Add the enhancement only when the capability is present. */
.canvas .visualization {
  background: transparent;
}

/* Provide a deliberate fallback for unsupported browsers. */
.no-canvas .visualization {
  border: 1px solid #69727c;
  padding: 1rem;
}

Use the class on the root element as the scope for enhancement styles. CSS classes and JavaScript properties are two ways to consume the same detection results; choose the layer where the behavior belongs.

4. Register a custom test

Use Modernizr.addTest when a built-in test does not express the capability your application needs. The test name is lowercased when exposed on the Modernizr object. A test may be a boolean or a function returning a boolean, and multiple tests can be supplied as an object.

Modernizr.addTest('featurekey', function () {
  return typeof window.exampleFeature === 'function';
});

if (Modernizr.featurekey) {
  enableExampleFeature();
} else {
  enableExampleFallback();
}

Replace exampleFeature with the actual API your code needs, and make the test reflect that dependency. This sample checks whether an API is callable; if your application depends on a specific behavior, test that behavior when it is safe and practical. Register the test after Modernizr loads and before application code reads its result or styles rely on its generated class.

For several custom tests, pass an object mapping names to booleans or test functions, as supported by the version in use:

Modernizr.addTest({
  featurekey: function () {
    return typeof window.exampleFeature === 'function';
  },
  anothercapability: false
});

5. Choose the right CSS detection helper

Different questions need different tests. Modernizr’s documented helpers include property, prefix, media-query, and rendered-style checks. Consult the documentation for the build and version you have, because a custom build must include the relevant helpers and tests.

Need API Use it for
Check an unprefixed CSS property testProp Whether a property is recognized.
Check a property including prefixed forms testAllProps Whether the property exists under a supported prefix.
Find a supported prefixed property name prefixed Code that needs the resolved property name.
Check a media query mq Whether a valid media query matches.
Check rendered behavior testStyles Inspecting DOM or style results that cannot be answered by property presence alone.

For example, test a property and value together when the value matters. Availability of a property name alone does not prove that a particular value or rendered result works as required. Modernizr 3 documentation notes that some CSS helpers use CSS.supports() where available.

6. Configure classes and build contents

Modernizr’s configuration controls let you tailor the generated build. The documented options include:

  • classPrefix: changes the prefix used for feature classes.
  • enableClasses: controls whether feature classes are added to the root element.
  • enableJSClass: controls the JavaScript-enabled root class behavior.

If you disable feature classes, JavaScript results can still be used, but CSS selectors depending on those classes will no longer work. If you change the class prefix, update your CSS to match. Generate a build containing the tests and helpers your code calls; a missing test cannot be relied on simply because another Modernizr build included it.

7. Check behavior, not just API presence

Detection reduces guesswork, but a positive result does not guarantee correct behavior in every context. Browser implementations can be incomplete or buggy, including cases where an API is exposed but does not work as expected. For a failure-prone or important feature, test the user-facing result as well and keep a usable fallback.

  1. Identify the exact capability the enhancement requires.
  2. Select a built-in test or write a custom test that measures that capability.
  3. Verify the enhanced behavior in the contexts that matter to your application.
  4. Keep the fallback available if the check fails or the feature later errors.

8. Troubleshooting

Symptom Likely cause Fix
Modernizr is undefined The script did not load, its path is wrong, or application code ran first. Check the browser’s network and console panels, correct the script path, and load Modernizr before dependent code.
A feature property is undefined The custom build may not include that test, or the property name differs from the documented result. Include the needed test in the build and check the exact API name in the documentation for that version.
The CSS fallback selector never matches Feature classes are disabled, the class prefix changed, or the stylesheet expects a different class spelling. Check the root element’s class list and align configuration and selectors.
A custom test class does not appear The test was registered after styles or code needed it, or its function did not return a boolean result. Register it after Modernizr loads but before dependent code, and return a boolean from the test.
The feature passes detection but fails in use The check measured API or property presence, not the exact behavior your application needs. Test the relevant behavior and add runtime error handling or a fallback.
A media query check gives an unexpected result The query may be invalid or valid but not match the current environment. Check query syntax and distinguish whether you need validity or a match under current conditions.
Old code expects Modernizr.load Modernizr 3 release notes deprecated it in favor of using yepnope.js directly and note that yepnope.js must be included for Modernizr.load to work in Modernizr 3. Verify the exact version or fork. Treat this as version-specific historical guidance, not a statement about every current build; follow that build’s documentation.

9. Performance, reliability, and cost

Build only the detects and helpers the project needs, and avoid running expensive custom checks repeatedly. If a custom test is costly, compute its result once and use the registered boolean. Loading Modernizr early can prevent a flash of unstyled fallback content, while delaying it can defer detection; account for this when choosing script placement.

Detection should guide progressive enhancement, not become a single point of failure. Keep core content available without the enhancement, and test results on the browsers and devices relevant to your users. Modernizr is a JavaScript library; its documented download/build workflow does not require a screenshot API or per-capture service charge. Any costs associated with your own hosting, build, or test infrastructure are separate.

10. Or skip the browser setup

If your goal is to capture how a page renders across conditions, ScreenshotNeo is a website screenshot API and MCP server for developers. A request returns a PNG, JPEG, WebP, or PDF. For example, capture a page as WebP:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for request options. Python equivalent:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)

Node.js equivalent:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', new Uint8Array(await res.arrayBuffer()));

ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and whether the request was billed. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card.

11. FAQ

Does Modernizr identify the browser?

Its purpose is to report feature support, so branch on the capability you need rather than a browser identity.

Can a custom Modernizr test add a CSS class?

Yes. A registered test contributes a result that can be exposed as a root class when class generation is enabled.

Does a passing test guarantee the feature will work?

No. A test can report support while an implementation still has a bug or behaves differently in the context your application uses.

Should I use Modernizr for every CSS declaration?

No. Use it where a capability check changes the experience; keep ordinary styling and baseline content simple.