What Does jQuery $.cssHooks Do?

The jQuery $.cssHooks object provides an internal mechanism to customize and extend how jQuery handles specific CSS properties via the .css() method. By defining custom get and set functions directly on $.cssHooks, developers can seamlessly normalize browser inconsistencies, support vendor prefixes, and create synthetic or composite CSS properties without modifying jQuery's core codebase.

Primary Uses of $.cssHooks

  1. Vendor Prefix Abstraction
    Modern CSS properties often require browser prefixes (such as -webkit-, -moz-, or -ms-) during experimental stages. With $.cssHooks, you can detect whether a standard or prefixed property is supported by the user's browser and map the standard property name to the correct prefixed version behind the scenes.

  2. Normalizing Browser Inconsistencies
    Different browsers may compute, return, or apply certain CSS values in non-standard ways. $.cssHooks allows you to intercept the reading or writing of a property to sanitize inputs, calculate dynamic values, or apply fallback behaviors for legacy browsers.

  3. Creating Custom CSS Properties
    You can define synthetic properties that do not natively exist in CSS. For example, you can create a custom rotate property that internally manipulates a complex transform: rotate(...) string.

Anatomy of a $.cssHook

A cssHook is an object assigned to a specific CSS property name inside $.cssHooks. It typically contains two methods: get and set.

$.cssHooks["propertyName"] = {
  get: function(elem, computed, extra) {
    // Logic to retrieve and return the property value
  },
  set: function(elem, value) {
    // Logic to apply the property value to the element
  }
};
  • get(elem, computed, extra): Invoked when reading a value via $(elem).css("propertyName").
    • elem: The DOM element being inspected.
    • computed: A boolean indicating if computed styles should be used.
    • extra: Optional filtering or formatting instructions.
  • set(elem, value): Invoked when writing a value via $(elem).css("propertyName", value).
    • elem: The DOM element being updated.
    • value: The incoming value passed to the .css() call.

Practical Example

The following example normalizes a non-standard or vendor-prefixed property (such as userSelect) across different browser engines:

(function($) {
  var style = document.documentElement.style;
  var prefixes = ["webkit", "moz", "ms"];
  var supportProp;

  // Detect supported property
  if ("userSelect" in style) {
    supportProp = "userSelect";
  } else {
    for (var i = 0; i < prefixes.length; i++) {
      var prefixed = prefixes[i] + "UserSelect";
      if (prefixed in style) {
        supportProp = prefixed;
        break;
      }
    }
  }

  // Define the hook if a prefix is required
  if (supportProp && supportProp !== "userSelect") {
    $.cssHooks.userSelect = {
      get: function(elem, computed, extra) {
        return $.css(elem, supportProp);
      },
      set: function(elem, value) {
        elem.style[supportProp] = value;
      }
    };
  }
})(jQuery);

Once this hook is defined, any standard call to $("#element").css("userSelect", "none") automatically targets the appropriate engine-specific property (webkitUserSelect, mozUserSelect, or msUserSelect) without requiring conditional logic in the application code.