jQuery jQuery.cssHooks

Intermediate
⏱️ 14 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Extend .css()

What You’ll Learn

jQuery.cssHooks lets you plug custom logic into how jQuery reads and writes CSS properties. This tutorial covers the get/set hook shape, vendor-prefix normalization, $.cssNumber, animation via $.fx.step, feature testing, and official jQuery patterns from the API docs.

01

Object

$.cssHooks

02

get

Read handler

03

set

Write handler

04

cssNumber

Skip auto px

05

fx.step

Animate hook

06

Since 1.4.3

Extension API

Introduction

Most of the time, .css() reads computed styles and writes inline properties without you thinking about browser quirks. Plugin authors and advanced developers sometimes need more control — mapping -webkit-border-radius to a single borderRadius name, reading rotation from a transform string, or teaching .animate() to tween a property jQuery does not know natively.

Available since jQuery 1.4.3, jQuery.cssHooks is the extension point behind that flexibility. jQuery ships built-in hooks for properties like opacity and scrollTop. You add entries keyed by camelCase property names; each entry may define get and set functions that jQuery calls whenever code uses .css() or .animate() on that property.

Understanding jQuery.cssHooks

jQuery.cssHooks is a plain object on the jQuery namespace. Keys are CSS property names in camelCase (for example borderRadius, scrollTop). Values are objects with optional get and set functions. When matched elements call .css("borderRadius"), jQuery looks up $.cssHooks.borderRadius.get if it exists; when setting, it calls set.

Think of cssHooks as adapters between jQuery’s uniform API and whatever the browser needs under the hood. Your hook receives the raw DOM element and the value; you decide how to read or write it. Once registered, callers use the normal .css() syntax — hyphenated (border-radius) or camelCase (borderRadius) — and jQuery routes through your adapter.

💡
Beginner Tip

You do not need cssHooks for everyday styling. Reach for them when you are building a jQuery plugin, normalizing legacy vendor prefixes, or exposing a custom animatable property that plain element.style cannot express directly.

📝 Syntax

A cssHook is registered by assigning an object to a property name on $.cssHooks:

Hook skeleton (official jQuery template)

jQuery
(function( $ ) {
  if ( !$.cssHooks ) {
    throw new Error( "jQuery 1.4.3+ is required" );
  }
  $(function () {
    $.cssHooks.someCSSProp = {
      get: function( elem, computed, extra ) {
        // return current value (String or Number)
      },
      set: function( elem, value ) {
        // write value to elem
      }
    };
  });
})( jQuery );
  • get(elem, computed, extra) — called when reading .css("someCSSProp"). Return the value jQuery should expose.
  • set(elem, value) — called when writing .css("someCSSProp", value). Apply the value to the element.
  • Register inside $(function(){ ... }) so jQuery does not overwrite your hook during its own initialization.

Feature test helper (styleSupport)

jQuery
function styleSupport( prop ) {
  var capProp = prop.charAt( 0 ).toUpperCase() + prop.slice( 1 ),
    prefixes = [ "Moz", "Webkit", "ms" ],
    div = document.createElement( "div" ),
    supportedProp;
  if ( prop in div.style ) {
    supportedProp = prop;
  } else {
    for ( var i = 0; i < prefixes.length; i++ ) {
      var vendorProp = prefixes[ i ] + capProp;
      if ( vendorProp in div.style ) {
        supportedProp = vendorProp;
        break;
      }
    }
  }
  div = null;
  $.support[ prop ] = supportedProp;
  return supportedProp;
}
  • Tests standard name first, then vendor-prefixed variants (WebkitBorderRadius, etc.).
  • Stores result on $.support[prop] for reuse inside your hook.

Unitless numbers — $.cssNumber

jQuery
$.cssNumber.someCSSProp = true;
  • By default jQuery appends px to numeric setter values for dimension properties.
  • Set $.cssNumber.propName = true to keep numbers unitless (opacity, z-index, custom degrees, etc.).

Animation — $.fx.step

jQuery
$.fx.step.someCSSProp = function( fx ) {
  $.cssHooks.someCSSProp.set( fx.elem, fx.now + fx.unit );
};
  • cssHooks alone extend .animate() for many numeric properties.
  • Add $.fx.step when the animation engine needs help applying intermediate values each frame.

Return value

  • Assigning to $.cssHooks does not return a jQuery object — it is a one-time registration.
  • After registration, .css() getters return whatever your get function returns; setters return the jQuery object as usual.

⚡ Quick Reference

GoalCode
Register a cssHook$.cssHooks.borderRadius = { get, set }
Safe registration timing$(function(){ $.cssHooks.prop = { ... }; });
Feature-test a propertyvar p = styleSupport("borderRadius")
Use hook via .css()$("#box").css("borderRadius", "10px")
Skip auto px suffix$.cssNumber.rotateDeg = true
Animate hooked property$("#box").animate({ borderRadius: 50 }, 600)
Custom animation step$.fx.step.borderRadius = function(fx){ ... }

📋 cssHooks vs .css() vs .animate() vs plugins

Four layers of jQuery styling — from everyday inline styles to low-level extension hooks.

.css()
get/set

Public API for reading computed values and writing inline styles

cssHooks
extend

Override how specific property names are retrieved or applied

.animate()
tween

Uses cssHooks automatically — add fx.step for complex values

$.cssNumber
units

Tell jQuery not to append px to numeric setters

Examples Gallery

Examples 1–5 follow patterns from the official jQuery API documentation. Use the Try-it links to run each snippet in the browser.

📚 Getting Started

Official jQuery patterns for registering and using cssHooks.

Example 1 — Official Demo: Basic get/set Skeleton

Register a borderRadius hook inside document ready, then set it with .css().

jQuery
$(function () {
  $.cssHooks.borderRadius = {
    get: function( elem ) {
      return $.css( elem, "borderRadius" );
    },
    set: function( elem, value ) {
      elem.style.borderRadius = value;
    }
  };
  $( "#box" ).css( "borderRadius", "16px" );
});
Try It Yourself

How It Works

The official skeleton wraps registration in document ready. get delegates to jQuery’s CSS reader; set writes directly to elem.style. Callers still use familiar .css() syntax.

Example 2 — Official Demo: Feature Test with styleSupport

Detect which border-radius property name the browser supports before registering a hook.

jQuery
function styleSupport( prop ) {
  var capProp = prop.charAt( 0 ).toUpperCase() + prop.slice( 1 ),
    prefixes = [ "Moz", "Webkit", "ms" ],
    div = document.createElement( "div" ),
    supportedProp;
  if ( prop in div.style ) {
    supportedProp = prop;
  } else {
    for ( var i = 0; i < prefixes.length; i++ ) {
      var vendorProp = prefixes[ i ] + capProp;
      if ( vendorProp in div.style ) {
        supportedProp = vendorProp;
        break;
      }
    }
  }
  div = null;
  $.support[ prop ] = supportedProp;
  return supportedProp;
}
styleSupport( "borderRadius" );
Try It Yourself

How It Works

Before normalizing vendor prefixes, detect support once. Store the winning property name on $.support so your hook’s get/set functions can reuse it without re-testing every call.

📈 Normalization & Animation

Complete hooks, unitless numbers, and tweening.

Example 3 — Official Demo: Complete borderRadius Hook

Combine feature testing with get/set so both hyphenated and camelCase names work.

jQuery
var borderRadius = styleSupport( "borderRadius" );
if ( borderRadius ) {
  $.cssHooks.borderRadius = {
    get: function( elem ) {
      return $.css( elem, borderRadius );
    },
    set: function( elem, value ) {
      elem.style[ borderRadius ] = value;
    }
  };
}
$( "#a" ).css( "borderRadius", "10px" );
$( "#b" ).css( "border-radius", "20px" );
Try It Yourself

How It Works

The official complete hook reads and writes through the detected property name. If the browser lacks any form of the property, skip registration — the style is not applied rather than throwing an error.

Example 4 — Special Units with $.cssNumber

Expose a custom rotateDeg property that stores degrees without jQuery appending px.

jQuery
$.cssNumber.rotateDeg = true;
$.cssHooks.rotateDeg = {
  get: function( elem ) {
    var m = ( elem.style.transform || "" ).match( /rotate\(([-\d.]+)deg\)/ );
    return m ? parseFloat( m[ 1 ] ) : 0;
  },
  set: function( elem, value ) {
    elem.style.transform = "rotate(" + parseFloat( value ) + "deg)";
  }
};
$( "#box" ).css( "rotateDeg", 45 );
Try It Yourself

How It Works

By default jQuery treats numeric setters as pixel dimensions. $.cssNumber.rotateDeg = true marks the property as unitless so 45 stays 45, not 45px. The hook maps that number to a transform: rotate(Ndeg) string.

Example 5 — Animating with cssHooks and $.fx.step

Click to tween borderRadius — cssHooks extend .animate() when combined with an fx step.

jQuery
$.cssHooks.borderRadius = {
  get: function( elem ) {
    return parseFloat( $.css( elem, "borderRadius" ) ) || 0;
  },
  set: function( elem, value ) {
    elem.style.borderRadius = value + "px";
  }
};
$.fx.step.borderRadius = function( fx ) {
  $.cssHooks.borderRadius.set( fx.elem, fx.now );
};
$( "#box" ).animate({ borderRadius: 40 }, 600 );
Try It Yourself

How It Works

cssHooks tell jQuery how to read and write a property; $.fx.step tells the animation engine how to apply intermediate numeric values each frame. Together they make custom properties animatable with familiar .animate() syntax.

🚀 Common Use Cases

  • Vendor-prefix normalization — map -webkit-border-radius and -moz-border-radius to one borderRadius hook.
  • Plugin development — ship a jQuery plugin that adds animatable custom properties without patching core.
  • Transform helpers — expose rotateDeg or scaleX as simple numeric cssHook properties.
  • Legacy browser support — feature-test once, store on $.support, branch inside get/set.
  • Scroll and opacity — study built-in hooks like scrollTop and opacity jQuery already registers.
  • Custom tweening — combine cssHooks with $.fx.step for smooth numeric animations.

🧠 How cssHooks Plug Into jQuery

1

Register hook

Assign { get, set } to $.cssHooks.propName inside document ready.

Setup
2

Caller uses .css()

.css("propName") or .css("propName", value) — same public API.

API
3

jQuery routes

If a hook exists, jQuery calls your get or set instead of default logic.

Dispatch
4

Animate optionally

.animate({ propName: n }) reuses the same hook; add $.fx.step if needed.

📝 Notes

  • Available since jQuery 1.4.3 — requires $.cssHooks to exist before registering.
  • Register hooks inside $(function(){ ... }) — jQuery initializes its own hooks at document ready.
  • Property keys use camelCase DOM names (borderRadius, not border-radius).
  • Hyphenated names still work at call sites — jQuery normalizes them to the hook key.
  • $.cssNumber.prop = true prevents automatic px suffix on numeric setters.
  • Built-in hooks include opacity, scrollTop, and scrollLeft — inspect $.cssHooks in DevTools.
  • If feature test finds no supported property, skip hook registration — do not throw unless your plugin requires it.

Browser Support

jQuery.cssHooks has been part of jQuery since 1.4.3+. Hooks run in whatever browser loads jQuery — your hook’s get/set logic must handle vendor differences via feature tests. Modern evergreen browsers rarely need prefix hooks for common CSS3 properties.

jQuery 1.4.3+

jQuery.cssHooks

Supported in jQuery 1.x, 2.x, and 3.x. cssHooks are a jQuery extension API, not a native browser feature — behavior depends on the get/set functions you write and the browsers you target.

100% With jQuery loaded
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
cssHooks Universal

Bottom line: Safe in any jQuery 1.4.3+ project. Feature-test CSS properties inside your hook for legacy prefix support.

Conclusion

jQuery.cssHooks is the extension point behind .css() and .animate(). Register get and set handlers on camelCase property names to normalize vendor prefixes, expose custom properties, and enable tweening.

Remember the official workflow: feature-test with styleSupport(), register inside document ready, use $.cssNumber for unitless values, and add $.fx.step when animations need per-frame help. For everyday styling, stick with .css() — cssHooks are for plugins and advanced cases.

💡 Best Practices

✅ Do

  • Register hooks inside $(function(){ ... })
  • Feature-test CSS properties once and cache on $.support
  • Use $.cssNumber for unitless numeric properties
  • Keep get/set functions small and focused on one property
  • Document custom property names if you expose them in a plugin

❌ Don’t

  • Register cssHooks for properties that work fine with plain .css()
  • Assign hooks before jQuery finishes its own cssHooks setup
  • Assume vendor-prefix hooks are still needed for modern CSS3 in 2026
  • Forget to skip registration when the browser lacks support
  • Mix multiple transform operations without reading the existing transform string

Key Takeaways

Knowledge Unlocked

Six things to remember about cssHooks

Extend .css() — power .animate().

6
Core concepts
? 02

get

Read

Getter
= 03

set

Write

Setter
# 04

cssNumber

No px

Units
~ 05

fx.step

Tween

Animate
06

ready

Timing

Safe

❓ Frequently Asked Questions

jQuery.cssHooks is an object on the jQuery namespace where you register get and set handlers for CSS property names. When you call .css('propertyName') or .animate({ propertyName: value }), jQuery routes through your hook instead of using the default inline-style logic — useful for vendor prefixes, computed transforms, and custom properties.
Use cssHooks when a CSS property needs special handling: mapping -webkit-border-radius to borderRadius, reading rotation from a transform string, or exposing a synthetic property that does not map 1:1 to element.style. For everyday color and width changes, plain .css() is enough. cssHooks are for plugin authors and advanced styling extensions.
jQuery initializes its own built-in cssHooks during document ready. If you assign $.cssHooks.myProp before that finishes, jQuery may overwrite your object. The official docs recommend wrapping registration in a document-ready callback so your get/set functions persist.
cssHooks define how to read and write a property. cssNumber is a separate lookup: when true for a property name, jQuery skips auto-appending 'px' to numeric setter values. Use cssNumber for unitless numbers like opacity, z-index, or a custom degree value in your hook.
Once a property has a cssHook with get and set, jQuery's animation engine can tween it. For simple numeric properties you may only need the hook. For complex values, add $.fx.step.propertyName to push intermediate values through your setter during each animation frame.
Rarely for common properties — modern browsers support standard border-radius, transform, and flex names. cssHooks remain valuable for understanding jQuery internals, maintaining legacy plugins, animating non-standard properties, and teaching how .css() and .animate() share one extension point.
Did you know?

jQuery uses cssHooks internally for properties that do not map cleanly to inline styles — scrollTop, scrollLeft, and opacity are built-in examples you can inspect on $.cssHooks in the console. The same mechanism that powered vendor-prefixed border-radius in 2010 now lets plugin authors expose synthetic properties like rotation degrees while keeping the familiar .css() and .animate() API.

Next: jQuery.cssNumber

Learn which CSS properties skip automatic px suffix in numeric setters.

jQuery.cssNumber tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful