How jQuery Automatically Handles CSS Vendor Prefixes

Modern web browsers often require vendor prefixes such as -webkit-, -moz-, or -ms- to support experimental or proprietary CSS features. Starting with jQuery 1.8, the library automatically handles these vendor prefixes behind the scenes when you use the .css() method. This article explains the internal mechanism jQuery uses to detect, map, and cache browser-specific properties, allowing developers to write clean, standard CSS property names without manual prefixing.

1. Camel-Casing and Normalization

When a CSS property name is passed into .css(), jQuery first normalizes it. If the property is passed in standard hyphenated CSS notation (for example, box-sizing or user-select), jQuery converts it into camelCase format (boxSizing, userSelect). This conversion aligns with how the Document Object Model (DOM) represents CSS properties on a standard HTML element's style object.

2. Testing Against the Element Style Object

To check if a browser supports a property natively without a prefix, jQuery inspects an empty test element (typically created via document.createElement("div")). It checks whether the camelCased property exists as an attribute on that test element's style object:

property in element.style

If the standard, unprefixed property exists, jQuery uses it directly.

3. Iterating Over Known Vendor Prefixes

If the standard property is not supported, jQuery searches for a prefixed alternative. It capitalizes the first letter of the camelCased property and prepends standard vendor prefixes in sequence:

  • Webkit (Chrome, Safari, newer Opera versions, iOS browsers)
  • Moz (Firefox)
  • ms (Internet Explorer, legacy Edge)
  • O (Legacy Opera)

For instance, if userSelect is not found, jQuery checks WebkitUserSelect, MozUserSelect, and msUserSelect against the element's style object until it finds a property that is defined.

4. Caching via jQuery.cssProps

Running feature detection every time a style is read or written would negatively impact performance. To avoid this overhead, jQuery stores the discovered working property name in an internal lookup dictionary called jQuery.cssProps.

Once a supported prefixed property (such as WebkitUserSelect) is identified for user-select, that mapping is cached. For all subsequent calls to .css("user-select", ...) on any element, jQuery bypasses the detection logic and immediately applies the cached vendor-prefixed property.

5. Fallback via cssHooks

For edge cases where vendor prefixing involves value differences rather than just property names (such as CSS gradients or flexbox syntax variations), jQuery provides the jQuery.cssHooks API. While the automatic prefixing mechanism handles standard property names natively, cssHooks allows jQuery's core and plugin authors to define custom getter and setter behaviors for complex, browser-divergent CSS implementations.