Skip to content

jQuery UI Hoja de referencia

Curated set of user interface interactions and widgets built on jQuery.

01

Getting Started

Installation via CDN

jQuery UI depends on jQuery core — always load jQuery before jquery-ui.js. The CSS provides default theming and is required for widgets like Datepicker and Dialog to display correctly. Version 1.13.x supports jQuery 1.8+.

jquery-ui
<!-- jQuery UI requires jQuery core first -->
<link rel="stylesheet"
      href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>

npm Installation

Installing via npm lets you tree-shake by importing only the widgets you need (e.g. jquery-ui/ui/widgets/datepicker). Importing the full 'jquery-ui' bundle includes every widget and effect. The CSS theme must be imported separately.

jquery-ui
# Install via npm
npm install jquery jquery-ui

# Import in your bundle
import $ from "jquery";
import "jquery-ui/ui/widgets/datepicker";
import "jquery-ui/themes/base/all.css";

// Or import the full bundle
import "jquery-ui";

Basic Widget Initialization

All jQuery UI widgets follow the same plugin pattern: $(selector).widgetName(options). Pass an options object to configure, call methods via the string syntax ('methodName', args...). Always wrap initialization in $(function(){}) or place script at end of body.

jquery-ui
$(function () {
  // Initialize a widget on a selector
  $("#datepicker").datepicker();
  $("#dialog").dialog();

  // Pass options as an object
  $("#accordion").accordion({
    active: false,
    collapsible: true,
  });

  // Get or set an option after init
  $("#accordion").accordion("option", "active", 1);
});

Widget Method Pattern

The string-based API is consistent across all widgets. 'option' getter/setter, 'enable'/'disable', 'widget' (returns the outermost element), and 'destroy' (restores original markup) are supported by every widget. Use destroy when removing elements to avoid memory leaks.

jquery-ui
// All widgets share the same API conventions
$("#dialog").dialog("open");              // call a method
$("#dialog").dialog("option", "title");   // get an option
$("#dialog").dialog("option", "modal", true); // set an option
$("#dialog").dialog("disable");           // disable widget
$("#dialog").dialog("enable");            // enable widget
$("#dialog").dialog("widget");            // get the wrapper element
$("#dialog").dialog("destroy");           // remove widget entirely

Theme Configuration

jQuery UI ships ~24 prebuilt themes. The 'base' theme is the default. ThemeRoller (themroller.jqueryui.com) generates custom themes. Load your own CSS after the base to override specific classes like .ui-widget-header or .ui-state-default.

jquery-ui
<!-- Default base theme -->
<link rel="stylesheet"
      href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">

<!-- Other bundled themes: ui-lightness, ui-darkness, smoothness, redmond, ... -->
<link rel="stylesheet"
      href="https://code.jquery.com/ui/1.13.2/themes/smoothness/jquery-ui.css">

<!-- Override theme with your own CSS -->
<link rel="stylesheet" href="jquery-ui.css">
<link rel="stylesheet" href="my-theme-overrides.css">

Class Naming Convention

The CSS framework uses a consistent ui-* naming convention. Interaction states (default, hover, active, focus) are applied automatically by widgets. You can use these classes directly in your own markup to match jQuery UI styling.

jquery-ui
/* jQuery UI CSS classes are namespaced with ui- */
.ui-widget         /* base widget class */
.ui-widget-header  /* header bar (accordion, datepicker) */
.ui-widget-content /* content area */
.ui-state-default  /* default interactive state */
.ui-state-hover    /* mouse-over state */
.ui-state-active   /* active/selected state */
.ui-state-focus    /* keyboard focus state */
.ui-state-disabled /* disabled state */
.ui-corner-all     /* rounded corners (themable) */
.ui-icon           /* base icon class */
02

Draggable

Basic Draggable

Making an element draggable is a single call. The element can then be moved with the mouse. The ui-widget-content class applies default theme styling. Draggable inherits positioning — relative/absolute/absolute is applied as needed.

jquery-ui
<!-- HTML -->
<div id="box" class="ui-widget-content" style="width:100px;height:100px;">
  Drag me
</div>

<!-- JS -->
<script>
  $(function () {
    $("#box").draggable();
  });
</script>

Draggable Options

Options control how dragging behaves. 'axis' limits movement to one axis, 'containment' restricts the drag region, 'grid' snaps to intervals, and 'revert' returns the element to its start position. 'helper: clone' drags a copy instead of the original.

jquery-ui
$("#box").draggable({
  axis: "x",              // constrain to x or y axis
  containment: "parent",  // or "window", "document", or selector
  cursor: "move",         // cursor while dragging
  cursorAt: { left: 5 },  // offset cursor from drag handle
  grid: [20, 20],         // snap to grid
  delay: 100,             // ms delay before drag starts
  distance: 5,            // px before drag starts
  revert: true,           // snap back to start
  revertDuration: 200,    // revert animation duration
  scroll: false,          // prevent auto-scroll
  helper: "clone",        // "original", "clone", or function
  opacity: 0.6,           // opacity while dragging
  zIndex: 1000,           // z-index while dragging
});

Drag Events

Three events fire during a drag: 'start' (once at the beginning), 'drag' (continuously while moving), and 'stop' (once at the end). The ui object provides position (relative to parent) and offset (relative to page). Heavy work in 'drag' can hurt performance.

jquery-ui
$("#box").draggable({
  start: function (event, ui) {
    console.log("Drag started", ui.position);
  },
  drag: function (event, ui) {
    // Fires continuously during drag
    console.log(ui.position.left, ui.position.top);
  },
  stop: function (event, ui) {
    console.log("Drag stopped at", ui.position);
    console.log("Offset:", ui.offset);
  },
});

Handle & Cancel

'handle' restricts drag initiation to a specific child element — useful when the whole box should be movable but only via a title bar. 'cancel' prevents dragging from certain elements like inputs or textareas where mouse interaction is needed for editing.

jquery-ui
<!-- Only the header acts as the drag handle -->
<div id="box" class="ui-widget-content">
  <div class="drag-handle">Drag from here</div>
  <div class="content">Some content here</div>
  <textarea>Editable content</textarea>
</div>

<script>
  $("#box").draggable({
    handle: ".drag-handle",   // only this starts the drag
    cancel: "textarea",       // these elements never start a drag
  });
</script>

Constrain Movement

Containment restricts where the element can be dragged. 'parent', 'window', 'document', a selector, or an explicit [x1,y1,x2,y2] array all work. Combined with 'grid', you can create precise, snapped positioning for layout editors or dashboards.

jquery-ui
// Constrain within a parent element
$("#box").draggable({ containment: "parent" });

// Constrain within the window
$("#box").draggable({ containment: "window" });

// Constrain within a specific selector
$("#box").draggable({ containment: "#drag-area" });

// Constrain to an explicit bounding box [x1, y1, x2, y2]
$("#box").draggable({ containment: [0, 0, 500, 300] });

// Snap to a 50px grid
$("#box").draggable({ grid: [50, 50] });

Snap to Elements

'snap' makes the draggable jump to align with target elements when close enough. 'snapMode' controls alignment: 'inner' (inside target), 'outer' (outside target), or 'both'. Useful for building diagram tools or dashboard layouts where elements should align.

jquery-ui
$(".card").draggable({
  snap: ".snap-target",     // selector of elements to snap to
  snapMode: "inner",        // "inner", "outer", or "both"
  snapTolerance: 30,        // px distance to trigger snap
});

// Snap to all siblings of the same class
$(".card").draggable({
  snap: ".card",
  snapTolerance: 20,
});
03

Droppable

Basic Droppable

Droppable defines a target area that accepts dragged elements. The 'drop' callback fires when a draggable is released over it. The ui.draggable property gives a reference to the dragged element so you can move or process it.

jquery-ui
<div id="draggable" class="ui-widget-content">Drag me</div>
<div id="droppable" class="ui-widget-header">Drop here</div>

<script>
  $(function () {
    $("#draggable").draggable();
    $("#droppable").droppable({
      drop: function (event, ui) {
        $(this).addClass("ui-state-highlight")
               .html("Dropped!");
      },
    });
  });
</script>

Droppable Options

'accept' filters which draggables are allowed — a selector or function. 'activeClass' and 'hoverClass' provide visual feedback. 'greedy: true' prevents nested droppables from both receiving the drop event, useful for nested drop zones.

jquery-ui
$("#droppable").droppable({
  accept: ".special",       // only accept matching draggables
  activeClass: "ui-state-default",  // class while a drag is active
  hoverClass: "ui-state-hover",     // class while draggable is over
  tolerance: "fit",         // drop detection mode
  greedy: true,             // stop event propagation
  disabled: false,          // disable the droppable
});

Drop Events

Five events cover the full drop lifecycle. 'activate'/'deactivate' fire when a matching drag starts/ends. 'over'/'out' fire when the draggable enters/leaves the zone. 'drop' fires only on a successful release. Use these for progressive visual feedback.

jquery-ui
$("#droppable").droppable({
  activate: function (event, ui) {
    // Fires when an accepted draggable starts moving
    $(this).addClass("ui-state-default");
  },
  deactivate: function (event, ui) {
    // Fires when the drag ends (drop or cancel)
    $(this).removeClass("ui-state-default");
  },
  over: function (event, ui) {
    // Draggable entered the drop zone
    $(this).addClass("ui-state-hover");
  },
  out: function (event, ui) {
    // Draggable left the drop zone
    $(this).removeClass("ui-state-hover");
  },
  drop: function (event, ui) {
    // Draggable was released here
    console.log("Dropped:", ui.draggable);
  },
});

Accept Selector

'accept' can be a selector string or a function returning boolean. The function receives the dragged element and runs for each candidate, letting you apply runtime logic like data attributes or computed states. Unaccepted draggables won't trigger drop events.

jquery-ui
<!-- HTML: red and blue boxes -->
<div class="red draggable">Red</div>
<div class="blue draggable">Blue</div>

<div id="red-bin" class="bin">Red bin</div>
<div id="blue-bin" class="bin">Blue bin</div>

<script>
  // Only accept elements matching the selector
  $("#red-bin").droppable({ accept: ".red" });
  $("#blue-bin").droppable({ accept: ".blue" });

  // Or use a function for dynamic logic
  $("#any-bin").droppable({
    accept: function (drag) {
      return $(drag).data("category") === "recyclable";
    },
  });
</script>

Tolerance Modes

Tolerance defines how much overlap is required for a drop to register. 'fit' is strictest (entire element inside). 'pointer' is based on the mouse cursor. 'intersect' (50% overlap) is a good balance for most UIs. 'touch' is the most lenient.

jquery-ui
$("#droppable").droppable({
  // "fit": draggable must be fully inside (default)
  tolerance: "fit",

  // "intersect": at least 50% overlap
  tolerance: "intersect",

  // "pointer": mouse pointer must be inside
  tolerance: "pointer",

  // "touch": any edge touching counts
  tolerance: "touch",
});

Visual Feedback with Classes

Combine activeClass (shown whenever an accepted drag is in progress) and hoverClass (shown when the draggable is over the zone) to give users clear feedback. In the drop handler, you typically append the draggable to re-parent it into the drop zone.

jquery-ui
<!-- CSS -->
<style>
  .drop-active { border: 2px dashed #ccc; }
  .drop-hover  { border: 2px solid #0a0; background: #efe; }
</style>

<!-- JS -->
$("#zone").droppable({
  accept: ".item",
  activeClass: "drop-active",
  hoverClass: "drop-hover",
  drop: function (event, ui) {
    $(this).append(ui.draggable);
    ui.draggable.css({ top: 0, left: 0 });
  },
});
04

Resizable

Basic Resizable

Resized adds resize handles to an element. By default a handle appears at the bottom-right (se) corner. The element must have positioning applied (relative/absolute) for the handles to anchor correctly.

jquery-ui
<div id="box" class="ui-widget-content">
  Resize me from the corner
</div>

<script>
  $(function () {
    $("#box").resizable();
  });
</script>

Resize Handles

'handles' controls which edges/corners get resize grips. Use compass directions: n, e, s, w, ne, se, sw, nw. The default is 'e, s, se'. You can provide custom handle elements by selector for full styling control.

jquery-ui
$("#box").resizable({
  handles: "n, e, s, w, ne, se, sw, nw",  // all eight handles
});

// Or specify handle elements
$("#box").resizable({
  handles: {
    n: ".n-handle",
    se: ".se-handle",
  },
});

Resizable Options

Options constrain and customize resizing. 'aspectRatio' keeps proportions (great for images/video). 'alsoResize' syncs another element. 'ghost' shows a faint preview during resize, with the actual size applied on release. min/max dimensions enforce bounds.

jquery-ui
$("#box").resizable({
  alsoResize: "#other",     // resize another element in sync
  animate: true,            // animate to final size
  animateDuration: 200,     // ms
  aspectRatio: 16 / 9,      // preserve width:height ratio
  autoHide: true,           // hide handles until hover
  containment: "parent",    // restrict resize within parent
  grid: [10, 10],           // snap to grid
  maxHeight: 400,
  maxWidth: 600,
  minHeight: 100,
  minWidth: 100,
  ghost: true,              // show a ghost outline while resizing
});

Resize Events

Like draggable, resize fires start/resize/stop. The ui object has 'size' (width, height) and 'position' (left, top). When resizing from north or west edges, both size and position change. Use the resize event to update dependent UI like live preview.

jquery-ui
$("#box").resizable({
  start: function (event, ui) {
    console.log("Resize start", ui.size, ui.position);
  },
  resize: function (event, ui) {
    // Fires continuously during resize
    ui.size.width;   // new width
    ui.size.height;  // new height
    ui.position.left; // new position (may change for n/w handles)
  },
  stop: function (event, ui) {
    console.log("Final size:", ui.size);
  },
});

Aspect Ratio & Constraints

Use aspectRatio (a number or boolean true to lock current ratio) for images and media. Combined with min/max constraints, you can prevent awkward sizes. Grid snapping aligns to intervals — useful for editor interfaces and layout tools.

jquery-ui
// Keep a 4:3 ratio
$("#photo").resizable({ aspectRatio: 4 / 3 });

// Keep ratio and stay within bounds
$("#photo").resizable({
  aspectRatio: 4 / 3,
  maxWidth: 800,
  maxHeight: 600,
  minWidth: 100,
  minHeight: 75,
});

// Snap to a grid of 20px
$("#grid-box").resizable({ grid: [20, 20] });

Animate & Ghost Modes

'animate' smoothly transitions to the new size after the mouse is released. 'ghost' shows a semi-transparent preview during the drag, applying the real change only on release. Together they create a polished, non-janky resize experience.

jquery-ui
// Animate to the final size after release
$("#box").resizable({
  animate: true,
  animateDuration: "slow",   // or ms number
  animateEasing: "swing",
});

// Show a ghost outline while dragging, apply on release
$("#box").resizable({
  ghost: true,
  helper: "ui-resizable-helper",  // class for the ghost
});

// Combine both
$("#box").resizable({ ghost: true, animate: true });
05

Selectable

Basic Selectable

Selectable turns a list of children into a selectable group. Click to select, or drag a lasso to select multiple. Hold Ctrl/Cmd to add to the selection, Shift to select a range. Selected items get the ui-selected class automatically.

jquery-ui
<ol id="selectable">
  <li class="ui-widget-content">Item 1</li>
  <li class="ui-widget-content">Item 2</li>
  <li class="ui-widget-content">Item 3</li>
</ol>

<script>
  $(function () {
    $("#selectable").selectable();
  });
</script>

Selectable Options

'filter' restricts which children participate. 'tolerance' controls lasso behavior: 'touch' selects on any overlap (default), 'fit' requires full enclosure. Set 'autoRefresh: false' for large lists to improve performance — call $(...).selectable('refresh') manually after layout changes.

jquery-ui
$("#selectable").selectable({
  filter: "li",            // which children can be selected
  tolerance: "touch",      // "touch" or "fit" for lasso overlap
  distance: 0,             // px before lasso starts
  delay: 0,                // ms delay before lasso starts
  autoRefresh: true,       // recompute positions on each drag
  disabled: false,
  cancel: "a, .no-select", // elements that never start selection
});

Select Events

Events fire during the selection lifecycle: 'selecting'/'unselecting' while dragging, 'selected'/'unselected' once confirmed, and 'start'/'stop' for the overall operation. Each ui object has the relevant element (selecting, selected, etc.).

jquery-ui
$("#selectable").selectable({
  selecting: function (event, ui) {
    // ui.selecting: element being lassoed
    $(ui.selecting).addClass("highlight");
  },
  selected: function (event, ui) {
    // ui.selected: element just confirmed selected
    console.log("Selected:", $(ui.selected).text());
  },
  unselecting: function (event, ui) {
    $(ui.unselecting).removeClass("highlight");
  },
  unselected: function (event, ui) {
    console.log("Unselected:", $(ui.unselected).text());
  },
  start: function (event, ui) { /* lasso started */ },
  stop: function (event, ui) { /* lasso released */ },
});

Filter Items

Use 'filter' to allow only specific children to be selected, and 'cancel' to exclude others. This is useful for galleries where some items (locked, read-only) shouldn't participate. The lasso will simply ignore non-matching elements.

jquery-ui
<ul id="gallery">
  <li class="selectable-item">Photo 1</li>
  <li class="locked">Locked</li>
  <li class="selectable-item">Photo 2</li>
</ul>

<script>
  $("#gallery").selectable({
    filter: ".selectable-item",  // only these can be selected
    cancel: ".locked",            // locked items never select
  });
</script>

Styling Selected Items

jQuery UI applies ui-selecting (during drag) and ui-selected (after release) classes automatically. Style these to give feedback. Read the current selection anytime via $('.ui-selected') within the container — handy for toolbars and bulk actions.

jquery-ui
/* CSS */
#selectable .ui-selecting {
  background: #feca40;        /* while dragging */
}
#selectable .ui-selected {
  background: #f39814;        /* confirmed selection */
  color: white;
}
#selectable li {
  margin: 3px; padding: 6px;
  border: 1px solid #ccc;
}

/* selected count badge */
function updateCount() {
  var n = $("#selectable .ui-selected").length;
  $("#count").text(n + " selected");
}
$("#selectable").on("selectablestop", updateCount);

Programmatic Selection

Call 'refresh' after adding/removing items so lasso hit-testing stays accurate. There's no built-in 'select' method, but you can toggle the ui-selected class manually. Clear by removing that class from all items.

jquery-ui
// Refresh positions after DOM changes
$("#selectable").selectable("refresh");

// Disable / enable
$("#selectable").selectable("disable");
$("#selectable").selectable("enable");

// Remove the widget
$("#selectable").selectable("destroy");

// Manually select an item (set the class)
$("#selectable li").eq(2).addClass("ui-selected");

// Clear all selections
$("#selectable .ui-selected").removeClass("ui-selected");
06

Sortable

Basic Sortable

Sortable makes list items reorderable by drag. Items are visually moved during the drag and the DOM order updates on release. Useful for task lists, photo galleries, and any priority-ordered content.

jquery-ui
<ul id="sortable">
  <li class="ui-widget-content">Item 1</li>
  <li class="ui-widget-content">Item 2</li>
  <li class="ui-widget-content">Item 3</li>
</ul>

<script>
  $(function () {
    $("#sortable").sortable();
  });
</script>

Sortable Options

Options refine sorting behavior. 'placeholder' styles the gap left behind; forcePlaceholderSize ensures it matches item dimensions. 'axis' restricts to horizontal/vertical. 'handle' designates a drag grip — ideal when the whole item has interactive children.

jquery-ui
$("#sortable").sortable({
  axis: "y",                // constrain to vertical
  cursor: "move",
  handle: ".handle",        // drag from this element only
  placeholder: "sortable-placeholder", // class for the drop preview
  forcePlaceholderSize: true, // match placeholder to item size
  helper: "clone",          // "original" or "clone"
  opacity: 0.7,
  revert: true,             // animate item into place
  tolerance: "pointer",     // "intersect" or "pointer"
  scroll: true,             // auto-scroll the page
  containment: "parent",    // restrict within parent
});

Sort Events

Key events: 'start'/'stop' bracket the sort. 'change' fires when the item's position changes during drag. 'update' fires only when the final order differs from the start — this is where you persist the new order, often via toArray() which returns item IDs in order.

jquery-ui
$("#sortable").sortable({
  start: function (event, ui) {
    ui.item;            // the dragged element
    ui.placeholder;     // the placeholder element
    ui.helper;          // the helper being dragged
  },
  change: function (event, ui) {
    // Position in list changed during drag
  },
  sort: function (event, ui) {
    // Fires continuously while sorting
  },
  beforeStop: function (event, ui) {
    // Just before the item is placed
  },
  stop: function (event, ui) {
    console.log("Sort ended");
  },
  update: function (event, ui) {
    // Order actually changed — persist it here
    var order = $(this).sortable("toArray");
    saveOrder(order);
  },
});

Connected Lists

'connectWith' links multiple sortables so items can be dragged between them — great for Kanban boards or pipeline managers. Each list still tracks its own order via toArray(). Use receive/remove events to react to cross-list transfers.

jquery-ui
<ul id="list-a" class="connected">
  <li>Task A1</li><li>Task A2</li>
</ul>
<ul id="list-b" class="connected">
  <li>Task B1</li>
</ul>

<script>
  $(".connected").sortable({
    connectWith: ".connected",  // allow moving between lists
    placeholder: "ui-state-highlight",
  }).disableSelection();
</script>

Placeholder & Helper

The placeholder is the empty space shown where the item will land — style it to give clear drop feedback. forcePlaceholderSize is important when items have varying heights. A custom helper function lets you show a simplified preview while dragging.

jquery-ui
$("#sortable").sortable({
  placeholder: "ui-state-highlight",  // class for the gap
  forcePlaceholderSize: true,
  helper: function (event, el) {
    // Return a custom helper element
    return $("<div class='custom-helper'>Moving...</div>");
  },
  cursorAt: { top: 10, left: 10 },
});

// Use a clone as the helper instead of moving the original
$("#sortable").sortable({ helper: "clone" });

Sort Methods

toArray() returns IDs in current order — most useful for persistence. serialize() builds a query string when IDs follow the 'name_number' convention. cancel() undoes the most recent sort. Call refresh() after programmatically adding items.

jquery-ui
// Get current order as an array of IDs
var order = $("#sortable").sortable("toArray");
// ["item-1", "item-3", "item-2"]

// Get option values
var placeholder = $("#sortable").sortable("option", "placeholder");

// Serialize items as a query string (uses id="name_number")
var data = $("#sortable").sortable("serialize");
// "item[]=1&item[]=2&item[]=3"

// Cancel the current sort (revert)
$("#sortable").sortable("cancel");

// Refresh positions after DOM changes
$("#sortable").sortable("refresh");

// Disable / enable / destroy
$("#sortable").sortable("disable");
$("#sortable").sortable("enable");
$("#sortable").sortable("destroy");
07

Accordion

Basic Accordion

Accordion expects pairs of header + content elements (header must come first). By default only one section is open at a time. The default header element is h3 but can be changed via the header option. Content panels follow each header.

jquery-ui
<div id="accordion">
  <h3>Section 1</h3>
  <div>Content for section 1</div>
  <h3>Section 2</h3>
  <div>Content for section 2</div>
  <h3>Section 3</h3>
  <div>Content for section 3</div>
</div>

<script>
  $(function () {
    $("#accordion").accordion();
  });
</script>

Accordion Options

Set 'collapsible: true' to allow all panels closed (default forces one open). 'heightStyle: content' sizes each panel to its content; 'fill' makes all panels equal height to the container; 'auto' uses the tallest panel's height.

jquery-ui
$("#accordion").accordion({
  active: 0,                 // index of open panel (false = all closed)
  collapsible: true,         // allow closing all panels
  disabled: false,
  animate: 200,              // ms or "ease name" or false
  heightStyle: "content",    // "auto", "fill", or "content"
  header: "h3",              // header selector
  icons: {
    header: "ui-icon-triangle-1-e",
    activeHeader: "ui-icon-triangle-1-s",
  },
  event: "click",            // event that toggles panels
});

Accordion Events

beforeActivate lets you veto a panel change by returning false — useful for unsaved-changes prompts. activate fires after the animation completes. The ui object gives old/new header and panel elements for both events.

jquery-ui
$("#accordion").accordion({
  beforeActivate: function (event, ui) {
    // ui.oldHeader, ui.oldPanel (closing)
    // ui.newHeader, ui.newPanel (opening)
    // Return false to cancel
    if ($(ui.newHeader).data("locked")) return false;
  },
  activate: function (event, ui) {
    // Fires after a panel finishes opening
    console.log("Opened:", ui.newHeader.text());
  },
  create: function (event, ui) {
    // Fires on initialization
    console.log("Accordion created, open:", ui.header.text());
  },
});

Custom Icons

icons maps the closed (header) and open (activeHeader) icon classes. Pass false to disable icons. You can use any icon library (FontAwesome, Material Icons) by providing the appropriate class names — the icon span is created automatically.

jquery-ui
$("#accordion").accordion({
  icons: {
    header: "ui-icon-circle-arrow-e",
    activeHeader: "ui-icon-circle-arrow-s",
  },
});

// Disable icons entirely
$("#accordion").accordion({ icons: false });

// Use your own icon classes (e.g. with FontAwesome)
$("#accordion").accordion({
  icons: {
    header: "fa fa-plus",
    activeHeader: "fa fa-minus",
  },
});

Collapsible & Multiple Sections

For a true 'multiple open at once' accordion, jQuery UI's accordion doesn't support it natively — instead initialize separate collapsible accordions per section, or use tabs. The 'collapsible: true' option only allows closing the currently open panel.

jquery-ui
// Allow all panels to be closed
$("#accordion").accordion({
  collapsible: true,
  active: false,   // start with all closed
});

// Make every section independently toggleable
// (a true multi-open accordion = separate collapsibles)
$(".section").each(function () {
  $(this).accordion({
    collapsible: true,
    active: false,
    header: ".section-header",
  });
});

Dynamic Accordion

Call refresh() after adding or removing panels so the widget re-binds. Use the active option to programmatically open a panel by index. The beforeActivate pattern is a clean way to lazy-load panel content via AJAX only when first opened.

jquery-ui
// Refresh after adding content
$("#accordion").append("<h3>New</h3><div>Content</div>");
$("#accordion").accordion("refresh");

// Switch the open panel
$("#accordion").accordion("option", "active", 2);

// Disable / enable
$("#accordion").accordion("disable");
$("#accordion").accordion("enable");

// Destroy
$("#accordion").accordion("destroy");

// Load content on demand (AJAX-style)
$("#accordion").accordion({
  beforeActivate: function (event, ui) {
    var panel = ui.newPanel;
    if (panel.is(":empty")) {
      panel.load("/api/section/" + ui.newHeader.data("id"));
    }
  },
});
08

Autocomplete

Basic Autocomplete

Pass a simple array of strings to 'source' for static suggestions. The widget filters by substring as the user types. Suggestions appear in a dropdown; selecting one fills the input. The list can also contain {label, value} objects for richer display.

jquery-ui
<label for="city">City:</label>
<input id="city" type="text">

<script>
  $(function () {
    var cities = ["London", "Paris", "Berlin", "Madrid", "Rome"];
    $("#city").autocomplete({ source: cities });
  });
</script>

Remote Data Source

When source is a URL, autocomplete sends a GET request with ?term= typed text and expects a JSON array. minLength delays the request until enough characters are typed to reduce server load. The delay option debounces rapid typing.

jquery-ui
$("#city").autocomplete({
  source: "/api/cities",   // server endpoint
  minLength: 2,            // start suggesting after 2 chars
  delay: 300,              // ms between keystroke and request
});

// The server should return JSON like:
// ["London", "Paris", "Berlin"]
// or [{ "label": "London, UK", "value": "London" }]

Autocomplete Options

autoFocus: true highlights the first suggestion so pressing Enter selects it immediately. position configures menu placement relative to the input using jQuery UI Position. appendTo is useful when the input is in an absolutely-positioned container with overflow issues.

jquery-ui
$("#city").autocomplete({
  source: cities,          // array, URL, or function
  minLength: 1,            // chars before suggestions appear
  delay: 300,              // ms between keystroke and request
  autoFocus: true,         // focus first item automatically
  appendTo: "#container",  // where to render the menu
  position: { my: "left top", at: "left bottom" },
  disabled: false,
});

Custom Source Function

A function source gives full control — useful for caching, custom filtering, or combining multiple endpoints. You MUST call response(results) with an array, even if empty. Each item can have arbitrary fields beyond label/value, accessible in the select handler.

jquery-ui
$("#city").autocomplete({
  source: function (request, response) {
    // request.term is the typed text
    // response() must be called with the results array
    $.getJSON("/api/cities", { q: request.term })
      .done(function (data) {
        response(data);
      })
      .fail(function () {
        response([]);  // always call response, even on error
      });
  },
  select: function (event, ui) {
    // ui.item.label, ui.item.value
    $("#city-id").val(ui.item.id);
  },
});

Autocomplete Events

focus fires as the user moves through suggestions (keyboard or hover). select fires when an item is chosen. change fires on blur and is the right place to validate that the final value exists in the source. Returning false prevents the default input-filling behavior.

jquery-ui
$("#city").autocomplete({
  source: cities,
  focus: function (event, ui) {
    // Fires when an item is highlighted (not selected)
    $("#preview").text(ui.item.label);
    return false;  // prevent setting the input value on focus
  },
  select: function (event, ui) {
    // Fires when an item is chosen
    $("#city").val(ui.item.label);
    $("#city-id").val(ui.item.value);
    return false;  // prevent default behavior
  },
  change: function (event, ui) {
    // Fires when input loses focus
    if (!ui.item) {
      // User typed something not in the list
      console.log("No match:", this.value);
    }
  },
});

Categories & Custom Rendering

Override _renderMenu or _renderItem to customize the dropdown layout. This example groups suggestions by category with header rows. The $.widget pattern extends the base autocomplete, so all original options and events still work. Common for search interfaces.

jquery-ui
$.widget("custom.catcomplete", $.ui.autocomplete, {
  _renderMenu: function (ul, items) {
    var that = this, currentCategory = "";
    $.each(items, function (index, item) {
      if (item.category !== currentCategory) {
        ul.append("<li class='ui-autocomplete-category'>"
          + item.category + "</li>");
        currentCategory = item.category;
      }
      that._renderItemData(ul, item);
    });
  },
});

// Use the new widget
$("#search").catcomplete({
  source: [
    { label: "Java", category: "Languages" },
    { label: "JavaScript", category: "Languages" },
    { label: "React", category: "Frameworks" },
  ],
});
09

Button

Basic Button

The button widget themes any clickable element (button, input[type=submit], a) with jQuery UI styling. It adds the ui-button class and manages hover/active/focus states. Anchors become button-styled, useful for navigation that should look like buttons.

jquery-ui
<!-- Apply to button, input, or anchor elements -->
<button id="btn">Click me</button>
<input type="submit" id="submit" value="Submit">
<a href="#" id="link" class="btn">Link button</a>

<script>
  $(function () {
    $("#btn").button();
    $("#submit").button();
    $("#link").button();
  });
</script>

Button Options

Combine 'icon' and 'showLabel' to create icon-only buttons (compact toolbars). 'iconPosition' controls whether the icon precedes or follows the text. Use 'label' to set the text programmatically, useful when it changes at runtime (e.g. Start/Stop toggle).

jquery-ui
$("#btn").button({
  disabled: false,
  text: true,              // show the label text
  icon: "ui-icon-gear",    // primary icon class
  iconPosition: "beginning", // "beginning" or "end"
  showLabel: true,         // text or icon only
  label: "Save",           // override the button's text
});

// Icon-only button (must set showLabel: false)
$("#icon-btn").button({
  icon: "ui-icon-disk",
  showLabel: false,
});

Buttonset (Radio/Checkbox Groups)

buttonset groups radio buttons or checkboxes into a single visually connected toolbar. In jQuery UI 1.12+, buttonset was deprecated in favor of controlgroup(), which is more flexible and works with any input type. Each input must have a matching label.

jquery-ui
<div id="size-set">
  <input type="radio" id="s1" name="size"><label for="s1">S</label>
  <input type="radio" id="s2" name="size" checked><label for="s2">M</label>
  <input type="radio" id="s3" name="size"><label for="s3">L</label>
</div>

<script>
  $("#size-set").buttonset();

  // For checkboxes (multi-select):
  // $("#check-set").controlgroup();  // 1.12+
</script>

Icons

jQuery UI ships a sprite of ~170 icons prefixed with ui-icon-. Common ones: ui-icon-gear, ui-icon-trash, ui-icon-search, ui-icon-close. Browse the full set at api.jqueryui.com/theming/icons. Toggle icons at runtime via the option method for play/pause-style toggles.

jquery-ui
// Primary icon
$("#save").button({ icon: "ui-icon-disk" });

// Icon only (no text)
$("#play").button({
  icon: "ui-icon-play",
  showLabel: false,
});

// Change icon at runtime
$("#play").button("option", "icon", "ui-icon-pause");

// Available icons include:
// ui-icon-gear, ui-icon-disk, ui-icon-trash,
// ui-icon-search, ui-icon-close, ui-icon-check,
// ui-icon-arrowthick-1-n/e/s/w, and many more

Split Button (Toolbar)

jQuery UI doesn't have a native split button — combine a regular button with an icon-only button and a hidden Menu to build one. The arrow button toggles the menu. This pattern is common in rich toolbars like email clients or document editors.

jquery-ui
<div class="toolbar">
  <button id="save">Save</button>
  <button id="save-arrow"><span class="ui-icon ui-icon-triangle-1-s"></span></button>
</div>

<script>
  $("#save").button();
  $("#save-arrow").button({ text: false, icon: "ui-icon-triangle-1-s" });

  $("#save-arrow").on("click", function () {
    $("#menu").menu("widget").show();
  });
</script>

<!-- Combine with a Menu for a true split button -->
<ul id="menu" style="display:none;">
  <li><div>Save</div></li>
  <li><div>Save As...</div></li>
  <li><div>Export</div></li>
</ul>

Button Methods

Use the option method to change label, icon, or disabled state at runtime — typical for stateful buttons like 'Submit' → 'Loading...'. The refresh method re-reads the element's state (useful for checkboxes toggled programmatically). destroy removes all styling.

jquery-ui
// Disable / enable
$("#btn").button("disable");
$("#btn").button("enable");

// Change options
$("#btn").button("option", "label", "Loading...");
$("#btn").button("option", "disabled", true);

// Get the button element
$("#btn").button("widget");

// Refresh after DOM changes (e.g. removing a class)
$("#btn").button("refresh");

// Remove the widget
$("#btn").button("destroy");
10

Datepicker

Basic Datepicker

Clicking or focusing the input opens a calendar popup. The selected date fills the input as text. The calendar shows the current month with navigation arrows for previous/next month. By default dates use the US format (mm/dd/yy).

jquery-ui
<label for="date">Pick a date:</label>
<input type="text" id="date">

<script>
  $(function () {
    $("#date").datepicker();
  });
</script>

Datepicker Options

minDate/maxDate accept a Date object, a number (days from today), or a string ('+1M +1W'). numberOfMonths displays multiple months — helpful for date-range pickers. changeMonth/changeYear add dropdowns for jumping to distant years.

jquery-ui
$("#date").datepicker({
  dateFormat: "yy-mm-dd",     // ISO format
  defaultDate: "+1",          // tomorrow when calendar opens
  minDate: 0,                 // no past dates (today+)
  maxDate: "+1Y",             // up to one year ahead
  numberOfMonths: 2,          // show 2 months side by side
  showButtonPanel: true,      // Today/Done buttons
  changeMonth: true,          // dropdown for month
  changeYear: true,           // dropdown for year
  showAnim: "fadeIn",         // open animation
  duration: "fast",
  firstDay: 1,                // start week on Monday
  showWeek: true,             // show week numbers
});

Date Format

The dateFormat option uses PHP-style tokens. 'yy' means four-digit year (the extra y is intentional). Use formatDate() method to convert a Date to a string with the same tokens, and parseDate() to reverse it.

jquery-ui
$("#date").datepicker({
  dateFormat: "yy-mm-dd",  // 2026-07-04
});

// Format tokens:
// d  - day of month, no leading zero (1)
// dd - day, two digits (01)
// D  - short day name (Mon)
// DD - full day name (Monday)
// m  - month, no leading zero (1)
// mm - month, two digits (01)
// M  - short month name (Jan)
// MM - full month name (January)
// y  - two-digit year (26)
// yy - four-digit year (2026)
// @  - Unix timestamp
// ! - Windows ticks

// Common formats:
// "mm/dd/yy"      -> 07/04/2026
// "yy-mm-dd"      -> 2026-07-04
// "DD, MM d, yy"  -> Friday, July 4, 2026

Min/Max Dates & Ranges

For a date-range picker, link two datepickers: when the start is chosen, set the end's minDate; when the end is chosen, set the start's maxDate. beforeShowDay lets you disable or style individual days — noWeekends is a built-in that blocks Saturdays and Sundays.

jquery-ui
// Restrict to a date range
$("#start").datepicker({
  minDate: 0,
  maxDate: "+6M",
  onSelect: function (dateText) {
    // Set the end date's minimum to the start date
    $("#end").datepicker("option", "minDate", dateText);
  },
});
$("#end").datepicker({
  minDate: 0,
  maxDate: "+6M",
  onSelect: function (dateText) {
    $("#start").datepicker("option", "maxDate", dateText);
  },
});

// Disable weekends
$("#date").datepicker({
  beforeShowDay: $.datepicker.noWeekends,
});

Localization

jQuery UI ships regional files in the i18n folder for ~40 locales. Load the file and apply with $.datepicker.regional['fr']. You can also override individual strings inline. The regional file sets month names, day names, firstDay, and dateFormat at once.

jquery-ui
// Set the regionalization
$("#date").datepicker($.datepicker.regional["fr"]);

// Override specific strings
$("#date").datepicker({
  monthNames: ["janvier","février","mars","avril","mai","juin",
               "juillet","août","septembre","octobre","novembre","décembre"],
  dayNamesMin: ["Di","Lu","Ma","Me","Je","Ve","Sa"],
  firstDay: 1,
  dateFormat: "dd/mm/yy",
  prevText: "Précédent",
  nextText: "Suivant",
  closeText: "Fermer",
  currentText: "Aujourd'hui",
});

// Include the regional file for built-in locales:
// <script src="jquery-ui/i18n/datepicker-fr.js"></script>

Inline Datepicker & Events

Apply datepicker to a div instead of an input for an always-visible inline calendar — great for booking interfaces. onSelect fires when a date is picked, onChangeMonthYear when navigating months. getDate/setDate work with Date objects for programmatic control.

jquery-ui
<!-- Inline (always visible) calendar -->
<div id="inline-calendar"></div>

<script>
  $("#inline-calendar").datepicker({
    onSelect: function (dateText, inst) {
      console.log("Selected:", dateText);
    },
    onChangeMonthYear: function (year, month, inst) {
      console.log("Viewing:", month + "/" + year);
    },
    beforeShow: function (input, inst) {
      // Fires before the popup opens
      return { /* override options */ };
    },
    onClose: function (dateText, inst) {
      // Fires when the popup closes
    },
  });

  // Methods
  $("#date").datepicker("setDate", "+7");  // set to a week from today
  $("#date").datepicker("getDate");        // returns a Date object
  $("#date").datepicker("option", "minDate", new Date(2026, 0, 1));
</script>
11

Dialog

Basic Dialog

The element's title attribute becomes the dialog title bar. The dialog is auto-opened by default and is draggable/resizable. The element is moved into a jQuery UI wrapper with proper z-index stacking. Close via the X button or pressing Escape.

jquery-ui
<div id="dialog" title="Basic dialog">
  <p>This is a simple dialog window.</p>
</div>

<script>
  $(function () {
    $("#dialog").dialog();
  });
</script>

Dialog Options

Set autoOpen: false to create the dialog hidden, then call dialog('open') when needed — this is the standard pattern for on-demand dialogs. modal adds an overlay that blocks page interaction. position uses the jQuery UI Position utility for precise placement.

jquery-ui
$("#dialog").dialog({
  autoOpen: false,           // don't open on init
  modal: true,               // dim the page behind
  width: 400,
  height: "auto",
  minWidth: 200,
  maxWidth: 600,
  resizable: true,
  draggable: true,
  closeOnEscape: true,
  position: { my: "center", at: "center", of: window },
  title: "Custom Title",     // override the title attr
  show: { effect: "fade", duration: 200 },
  hide: { effect: "fade", duration: 200 },
});

Dialog Buttons

buttons accepts an array (preferred, allows icons and per-button options) or an object (text: handler). Inside a handler, 'this' is the dialog element — call $(this).dialog('close') to dismiss. Buttons are auto-themed and right-aligned by default.

jquery-ui
$("#dialog").dialog({
  buttons: [
    {
      text: "Save",
      icon: "ui-icon-disk",
      click: function () {
        saveForm();
        $(this).dialog("close");
      },
    },
    {
      text: "Cancel",
      click: function () {
        $(this).dialog("close");
      },
    },
  ],
});

// Shortcut object form (1.12+)
$("#dialog").dialog({
  buttons: {
    "Save": function () { saveForm(); $(this).dialog("close"); },
    "Cancel": function () { $(this).dialog("close"); },
  },
});

Dialog Events

beforeClose is the gatekeeper — return false to keep the dialog open (useful for unsaved-changes warnings). close fires after the dialog is dismissed, the right place to reset form state or free resources. drag/resize events mirror those of the underlying interactions.

jquery-ui
$("#dialog").dialog({
  beforeClose: function (event, ui) {
    // Return false to prevent closing
    if (!confirm("Discard changes?")) return false;
  },
  open: function (event, ui) {
    console.log("Dialog opened");
  },
  close: function (event, ui) {
    console.log("Dialog closed");
    // Clean up form state
    $(this).find("form")[0].reset();
  },
  focus: function (event, ui) {
    // Dialog gained focus
  },
  dragStart: function (event, ui) { /* dragging started */ },
  dragStop: function (event, ui) { /* dragging ended */ },
  resizeStart: function (event, ui) { /* resizing started */ },
  resizeStop: function (event, ui) { /* resizing ended */ },
});

Modal & Confirmation Dialog

Create a dialog from a dynamically-built element for one-off confirmations. The modal overlay prevents interaction with the rest of the page. Always destroy and remove the element in the close handler to avoid leaking DOM nodes when the dialog is dismissed.

jquery-ui
function confirmDialog(message, onConfirm) {
  $("<div>" + message + "</div>").dialog({
    modal: true,
    title: "Confirm",
    buttons: {
      "OK": function () {
        onConfirm();
        $(this).dialog("close");
      },
      "Cancel": function () {
        $(this).dialog("close");
      },
    },
    close: function () {
      $(this).dialog("destroy").remove();  // clean up
    },
  });
}

// Usage
confirmDialog("Delete this item?", function () {
  deleteItem();
});

AJAX Content & Methods

Use the open event to AJAX-load content and initialize any nested widgets. Always clear content on close so the next open is fresh. moveToTop raises the dialog above others in z-index — useful for stacked dialogs. isOpen is a boolean getter for conditional logic.

jquery-ui
// Load content from a URL when opening
function openEditDialog(id) {
  var $dlg = $("#edit-dialog");
  $dlg.dialog({
    autoOpen: false,
    modal: true,
    open: function () {
      $dlg.load("/api/edit/" + id, function () {
        // Initialize widgets in loaded content
        $dlg.find(".datepicker").datepicker();
      });
    },
    close: function () {
      $dlg.empty();  // clear for next open
    },
  });
  $dlg.dialog("open");
}

// Common methods
$("#dialog").dialog("open");
$("#dialog").dialog("close");
$("#dialog").dialog("isOpen");   // returns boolean
$("#dialog").dialog("moveToTop"); // bring to front
$("#dialog").dialog("option", "title", "New Title");
13

Progressbar

Basic Progressbar

Progressbar shows a horizontal bar filled to a percentage (0-100). The value option sets the current progress. The bar auto-themes with jQuery UI styling. The container's width determines the total bar width — set it via CSS.

jquery-ui
<div id="progress"></div>

<script>
  $(function () {
    $("#progress").progressbar({ value: 37 });
  });
</script>

Indeterminate Mode

Setting value to false puts the bar in indeterminate mode — an animated stripe indicates 'something is happening' without a specific percent. Use this when the total is unknown (e.g. waiting on a server). Switch back to a number once you can track progress.

jquery-ui
<div id="progress"></div>

<script>
  // Set value to false for an indeterminate (animated) bar
  $("#progress").progressbar({ value: false });

  // Switch to determinate later when you know the percent
  $("#progress").progressbar("option", "value", 50);
</script>

Progressbar Options

The 'max' option lets you use non-100 scales (e.g. max: 1000 for a download in KB). The value is interpreted as a fraction of max. The classes option (1.12+) lets you add custom classes to specific internal elements for fine-grained theming.

jquery-ui
$("#progress").progressbar({
  value: 0,           // 0-100, or false for indeterminate
  max: 100,           // upper bound (default 100)
  disabled: false,
  // 1.12+ supports a 'classes' option for theming
  classes: {
    "ui-progressbar": "highlight",
    "ui-progressbar-value": "animated",
  },
});

Updating Value

Update the bar by setting the value option. A setInterval loop simulates progress for uploads or long-running tasks. For real uploads, use the XHR upload progress event to update value based on bytes transferred. Always clear the timer when done.

jquery-ui
// Simulate a file upload
var progress = 0;
$("#progress").progressbar({ value: 0 });

var timer = setInterval(function () {
  progress += 5;
  $("#progress").progressbar("option", "value", progress);
  if (progress >= 100) {
    clearInterval(timer);
    console.log("Complete!");
  }
}, 200);

// Get current value
var current = $("#progress").progressbar("option", "value");

Change Event & Custom Labels

change fires whenever the value updates, complete fires at 100% — both are useful for dynamic styling or labels. To show the percentage text, add an absolutely-positioned label over the bar. Update it inside the change handler to keep it in sync.

jquery-ui
$("#progress").progressbar({
  value: 0,
  change: function () {
    var v = $("#progress").progressbar("value");
    $("#progress .ui-progressbar-value")
      .css("background", v < 50 ? "#fa0" : "#0a0");
  },
  complete: function () {
    $("#progress .ui-progressbar-value").css("background", "#0a0");
    $("#progress-label").text("Done!");
  },
});

// Overlay a text label
$("#progress").append(
  '<div id="progress-label" style="position:absolute;left:50%;top:0;">Loading...</div>'
);
14

Selectmenu

Basic Selectmenu

Selectmenu replaces the native select dropdown with a jQuery UI themed version. It supports all native features (selected, disabled options) and adds icons, custom rendering, and consistent cross-browser styling. The underlying select stays in sync, so forms submit normally.

jquery-ui
<label for="speed">Speed:</label>
<select id="speed">
  <option>Slower</option>
  <option>Slow</option>
  <option selected="selected">Medium</option>
  <option>Fast</option>
  <option>Faster</option>
</select>

<script>
  $(function () {
    $("#speed").selectmenu();
  });
</script>

Selectmenu Options

Set width to null to use the element's CSS width, or a number for explicit pixels. The default width auto-sizes to the longest option. position controls menu placement relative to the button. appendTo is useful for selectmenus inside dialogs or iframes.

jquery-ui
$("#speed").selectmenu({
  disabled: false,
  width: null,            // null = CSS width, number = px
  icons: { button: "ui-icon-triangle-1-s" },
  appendTo: null,         // where to render the menu
  position: { my: "left top", at: "left bottom" },
});

Selectmenu Events

change is the main event — fires when the user picks a different option. ui.item.value is the option's value attribute, ui.item.label is its text. select fires just before change and can be cancelled by returning false — useful for validation.

jquery-ui
$("#speed").selectmenu({
  change: function (event, ui) {
    // ui.item has the selected option's data
    console.log("Selected:", ui.item.value);
    console.log("Label:", ui.item.label);
  },
  focus: function (event, ui) {
    // Item highlighted in the dropdown
  },
  open: function (event, ui) {
    // Dropdown just opened
  },
  close: function (event, ui) {
    // Dropdown just closed
  },
  select: function (event, ui) {
    // Fires before change; return false to cancel
  },
});

Custom Rendering

Override _renderItem to add icons, descriptions, or custom HTML to each option. The item.element gives access to the original <option> so you can read data attributes. This is the standard way to build rich dropdowns like project selectors with status icons.

jquery-ui
$("#projects").selectmenu({
  // Render each item in the dropdown
  format: function (item) {
    // (deprecated in 1.12 — use _renderItem instead)
  },
});

// 1.12+ custom rendering via widget extension
$.widget("custom.iconselectmenu", $.ui.selectmenu, {
  _renderItem: function (ul, item) {
    var li = $("<li>"), wrapper = $("<div>", { text: item.label });
    if (item.disabled) li.addClass("ui-state-disabled");
    $("<span>", { class: "ui-icon " + item.element.data("icon") })
      .appendTo(wrapper);
    return li.append(wrapper).appendTo(ul);
  },
});

$("#projects").iconselectmenu();

Methods

To set the value, use the native .val() on the select then call refresh() to update the widget's display. Always call refresh() after adding, removing, or changing options in the underlying select so the widget reflects the new state.

jquery-ui
// Open / close programmatically
$("#speed").selectmenu("open");
$("#speed").selectmenu("close");

// Get or set the value
var val = $("#speed").selectmenu("option", "value");  // not standard
$("#speed").val("fast").selectmenu("refresh");  // use .val() + refresh

// Refresh after modifying the underlying select
$("#speed").append("<option>New</option>");
$("#speed").selectmenu("refresh");

// Disable / enable
$("#speed").selectmenu("disable");
$("#speed").selectmenu("enable");

// Get the button or menu element
$("#speed").selectmenu("widget");    // the button wrapper
$("#speed").selectmenu("menuWidget"); // the menu ul

// Destroy
$("#speed").selectmenu("destroy");

Optgroups & Disabled Options

Selectmenu respects native <optgroup> elements — they render as non-selectable group headers with proper theming. The disabled attribute on individual options is also honored, showing them greyed and preventing selection. Forms still submit the selected value.

jquery-ui
<select id="category">
  <optgroup label="Frontend">
    <option value="react">React</option>
    <option value="vue">Vue</option>
  </optgroup>
  <optgroup label="Backend">
    <option value="node">Node.js</option>
    <option value="django" disabled>Django (deprecated)</option>
  </optgroup>
</select>

<script>
  $("#category").selectmenu({
    width: 200,
    change: function (event, ui) {
      console.log("Picked:", ui.item.value);
    },
  });
</script>
15

Slider

Basic Slider

Slider creates a draggable handle on a horizontal track. The default range is 0-100 with the handle starting at 0. The track is fully themed. Set dimensions via CSS on the container — width for horizontal, height for vertical sliders.

jquery-ui
<div id="slider"></div>

<script>
  $(function () {
    $("#slider").slider();
  });
</script>

Slider Options

Use 'values' (array) instead of 'value' for a two-handle range slider. 'range: true' shades the area between handles; 'range: min' shades from the handle to the min; 'range: max' shades from the handle to the max. 'step' must divide evenly into (max - min).

jquery-ui
$("#slider").slider({
  min: 0,
  max: 100,
  step: 1,                  // increment size
  value: 50,                // single value
  values: [25, 75],         // two-handle range (omit 'value')
  orientation: "horizontal", // or "vertical"
  range: true,              // or "min", "max"
  disabled: false,
  animate: "fast",          // or ms, or false
});

Slider Events

slide fires continuously during dragging — ideal for live-updating a label. Returning false inside slide cancels the movement, useful for constraining values dynamically. change fires after release and on programmatic option changes; use it to persist the value.

jquery-ui
$("#slider").slider({
  start: function (event, ui) {
    // User started dragging a handle
    console.log("Start:", ui.value || ui.values);
  },
  slide: function (event, ui) {
    // Fires continuously during drag
    // Return false to prevent the handle from moving
    $("#label").text(ui.value);
  },
  change: function (event, ui) {
    // Fires after the handle is released (and on programmatic change)
    saveValue(ui.value);
  },
  stop: function (event, ui) {
    // User released the handle
  },
});

Range Slider

A two-handle range slider is built by setting range: true and providing a values array. ui.values[0] is the lower handle, ui.values[1] is the upper. The handles cannot cross. This is the classic pattern for price or date-range filters.

jquery-ui
<div id="range-slider"></div>
<p>Price: $<span id="min-price"></span> - $<span id="max-price"></span></p>

<script>
  $("#range-slider").slider({
    range: true,
    min: 0,
    max: 500,
    values: [75, 300],
    slide: function (event, ui) {
      $("#min-price").text(ui.values[0]);
      $("#max-price").text(ui.values[1]);
    },
  });
</script>

Vertical & Orientations

Vertical sliders need an explicit height set via CSS — width applies to the cross-axis. The handle moves up/down instead of left/right. The range shading works the same way. Useful for audio mixers, equalizers, or any UI where vertical orientation is more natural.

jquery-ui
// Vertical slider
$("#vertical").slider({
  orientation: "vertical",
  min: 0,
  max: 100,
  value: 60,
});

// Vertical range
$("#vertical-range").slider({
  orientation: "vertical",
  range: true,
  min: 0,
  max: 100,
  values: [20, 80],
});

/* CSS: vertical sliders need a height */
/* #vertical { height: 200px; } */
</script>

Slider Methods

For range sliders, use values() (no args) to get an array, values(index, value) to set one handle, or values(array) to set both. Setting options like min/max/step at runtime automatically re-positions the handles within the new bounds.

jquery-ui
// Get or set the value
$("#slider").slider("value");
$("#slider").slider("value", 75);

// Get or set both handles of a range slider
var vals = $("#slider").slider("values");  // [25, 75]
$("#slider").slider("values", 0, 30);      // set lower handle
$("#slider").slider("values", [30, 90]);   // set both

// Get or set options
$("#slider").slider("option", "max", 200);
$("#slider").slider("option", "disabled", true);

// Disable / enable / destroy
$("#slider").slider("disable");
$("#slider").slider("enable");
$("#slider").slider("destroy");
16

Spinner

Basic Spinner

Spinner adds up/down buttons to a text input for numeric entry. Users can type directly, click the buttons, or use the arrow keys. Holding a button accelerates the increment. The input's value is parsed as a number on every change.

jquery-ui
<label for="qty">Quantity:</label>
<input id="qty" type="text" value="1">

<script>
  $(function () {
    $("#qty").spinner();
  });
</script>

Spinner Options

min/max enforce bounds — the buttons won't go beyond them. step controls increment size (use decimals like 0.1 for fine control). numberFormat with culture enables localized formatting (e.g. 'C' with 'ja-JP' shows yen). Globalize.js must be loaded for culture support.

jquery-ui
$("#qty").spinner({
  min: 0,                   // minimum value
  max: 100,                 // maximum value
  step: 1,                  // increment size
  page: 10,                 // page up/down increment
  numberFormat: "n",        // "n" for number, "C" for currency
  culture: "en-US",         // locale for formatting
  disabled: false,
  incremental: true,        // accelerate while holding
  icons: {
    up: "ui-icon-triangle-1-n",
    down: "ui-icon-triangle-1-s",
  },
});

Number Formatting & Culture

With Globalize.js loaded, spinner formats values per the specified culture — currency symbols, decimal separators, and grouping all localize. numberFormat 'C' is currency, 'n' is number with optional decimal count (n2 = 2 decimals). Useful for internationalized forms.

jquery-ui
<!-- Requires Globalize.js for culture support -->
<script src="globalize.js"></script>
<script src="globalize.culture.ja-JP.js"></script>

<script>
  // Currency spinner (Japanese yen)
  $("#price").spinner({
    numberFormat: "C",
    culture: "ja-JP",
    step: 100,
    min: 0,
  });

  // Decimal spinner
  $("#weight").spinner({
    step: 0.01,
    numberFormat: "n2",  // 2 decimal places
    min: 0,
  });
</script>

Spinner Events

spin fires on each increment/decrement (button click or arrow key). Returning false cancels the change — ideal for custom validation. change fires on blur; ui.value is null if the input doesn't parse as a valid number, the place to show validation errors.

jquery-ui
$("#qty").spinner({
  spin: function (event, ui) {
    // Fires when a button is clicked or arrow pressed
    // ui.value is the new value
    // Return false to cancel the change
    if (ui.value > 10) {
      alert("Max 10 per order");
      return false;
    }
  },
  change: function (event, ui) {
    // Fires when the value changes and input loses focus
    // ui.value may be null if invalid
    if (ui.value === null) {
      alert("Please enter a valid number");
    }
  },
  start: function (event, ui) { /* spin started */ },
  stop: function (event, ui) { /* spin stopped */ },
});

Custom Step & Methods

stepUp/stepDown/pageUp/pageDown simulate button presses programmatically. value() with no argument is a getter; with an argument it's a setter that runs through validation. Custom spin handlers let you build non-numeric spinners like times, colors, or custom units.

jquery-ui
// Time spinner (steps of 15 minutes)
$("#time").spinner({
  step: 15,
  min: 0,
  max: 1439,  // 24 * 60 - 1
  numberFormat: "n0",
  spin: function (event, ui) {
    // Wrap around at midnight
    if (ui.value > 1439) return false;  // or wrap: $(this).spinner("value", 0);
  },
});

// Methods
$("#qty").spinner("value");        // get current value
$("#qty").spinner("value", 5);     // set value
$("#qty").spinner("stepUp");       // increment by one step
$("#qty").spinner("stepDown");     // decrement by one step
$("#qty").spinner("pageUp");       // increment by 'page' steps
$("#qty").spinner("pageDown");
$("#qty").spinner("disable");
$("#qty").spinner("enable");
$("#qty").spinner("destroy");

Validation & Custom Parsing

Override _parse and _format to build spinners for non-decimal values — hex colors, times, angles, or any custom unit. _parse converts the input text to a number; _format converts back for display. This is the cleanest way to extend spinner for domain-specific inputs.

jquery-ui
// Custom spinner for hexadecimal colors
$.widget("custom.hexspinner", $.ui.spinner, {
  _parse: function (value) {
    // String -> number
    return parseInt(value, 16);
  },
  _format: function (value) {
    // number -> string
    return value.toString(16).toUpperCase().padStart(6, "0");
  },
});

$("#color").hexspinner({
  min: 0x000000,
  max: 0xffffff,
  step: 0x10,
});

// Prevent invalid input
$("#qty").on("keydown", function (e) {
  if (e.key === "-" && $(this).spinner("option", "min") >= 0) {
    e.preventDefault();
  }
});
17

Tabs

Basic Tabs

Tabs expects a ul of links pointing to content panel IDs, followed by the panels themselves. The link hrefs (#tab-1) connect tabs to panels. The first tab is active by default. Tabs are keyboard-navigable (arrows, Home, End) and ARIA-compliant.

jquery-ui
<div id="tabs">
  <ul>
    <li><a href="#tab-1">First</a></li>
    <li><a href="#tab-2">Second</a></li>
    <li><a href="#tab-3">Third</a></li>
  </ul>
  <div id="tab-1">Content 1</div>
  <div id="tab-2">Content 2</div>
  <div id="tab-3">Content 3</div>
</div>

<script>
  $(function () {
    $("#tabs").tabs();
  });
</script>

Tabs Options

active sets the initially open tab by index (or false to start collapsed). heightStyle 'fill' makes all panels equal to the container height; 'content' sizes each to its own content (default). 'event: mouseover' creates hover-activated tabs.

jquery-ui
$("#tabs").tabs({
  active: 0,            // index of active tab (false = all hidden)
  collapsible: false,   // allow closing the active tab
  disabled: [],         // array of disabled indices
  event: "click",       // event to switch tabs ("mouseover" etc.)
  heightStyle: "content", // "auto", "fill", or "content"
  show: { effect: "fadeIn", duration: 200 },
  hide: { effect: "fadeOut", duration: 200 },
});

Tabs Events

beforeActivate is the gatekeeper — return false to block switching (e.g. unsaved changes warning). activate fires after the switch completes. beforeLoad/load are for AJAX tabs — beforeLoad lets you customize or cancel the request; load fires on success.

jquery-ui
$("#tabs").tabs({
  beforeActivate: function (event, ui) {
    // ui.newTab, ui.newPanel (opening)
    // ui.oldTab, ui.oldPanel (closing)
    // Return false to cancel the switch
    if ($(ui.newPanel).find("form").hasUnsavedChanges()) {
      return confirm("Discard changes?");
    }
  },
  activate: function (event, ui) {
    // Fires after the new tab is shown
    console.log("Now on:", ui.newTab.text());
  },
  beforeLoad: function (event, ui) {
    // For AJAX tabs — fires before loading remote content
    ui.jqXHR.error(function () {
      ui.panel.text("Failed to load content.");
    });
  },
  load: function (event, ui) {
    // AJAX content finished loading
  },
});

AJAX Tabs

When a tab's href is a URL (not an anchor), tabs loads the content via AJAX on activation. The response replaces the panel. beforeLoad lets you show a spinner, configure the AJAX request, or cancel it. Loaded content is cached for the session by default in 1.12+.

jquery-ui
<div id="tabs">
  <ul>
    <li><a href="#local">Local</a></li>
    <li><a href="remote.html">Remote (AJAX)</a></li>
    <li><a href="api/data.json">API Data</a></li>
  </ul>
  <div id="local">This content is in the page.</div>
  <!-- Remote panels are created automatically -->
</div>

<script>
  $("#tabs").tabs({
    beforeLoad: function (event, ui) {
      // Show a loading indicator
      ui.panel.html("Loading...");
      // Cache the loaded content
      ui.ajaxSettings.cache = true;
    },
  });
</script>

Collapsible & Sortable Tabs

With collapsible: true, clicking the active tab closes it (no tab remains open). Pairing tabs with sortable on the nav lets users reorder tabs by dragging. After adding or removing tabs/panels, call refresh() so the widget re-binds the new structure.

jquery-ui
// Allow collapsing the active tab
$("#tabs").tabs({ collapsible: true });

// Make tabs reorderable by drag
$("#tabs").tabs().find(".ui-tabs-nav").sortable({
  axis: "x",
  stop: function () {
    $("#tabs").tabs("refresh");
  },
});

// Dynamically add a new tab
function addTab(id, label, content) {
  var nav = $("#tabs .ui-tabs-nav");
  nav.append('<li><a href="#' + id + '">' + label + '</a></li>');
  $("#tabs").append('<div id="' + id + '">' + content + '</div>');
  $("#tabs").tabs("refresh");
}

Tabs Methods

disable/enable accept an index or array of indices. The active option is both getter and setter for the current tab — use it to programmatically switch. load() reloads AJAX content for a tab. refresh() is essential after adding, removing, or reordering tabs.

jquery-ui
// Disable / enable specific tabs
$("#tabs").tabs("disable", 1);       // disable second tab
$("#tabs").tabs("enable", 1);
$("#tabs").tabs("option", "disabled", [0, 2]);  // disable multiple

// Switch to a tab by index
$("#tabs").tabs("option", "active", 2);

// Reload an AJAX tab
$("#tabs").tabs("load", 1);

// Refresh after structural changes
$("#tabs").tabs("refresh");

// Get the active tab index
var active = $("#tabs").tabs("option", "active");

// Destroy
$("#tabs").tabs("destroy");
18

Tooltip

Basic Tooltip

Calling tooltip() on document replaces all native title tooltips with themed jQuery UI versions. The title attribute content becomes the tooltip text. Tooltips appear on hover and disappear on mouseout, with smooth fade animation by default.

jquery-ui
<label for="age">Age:</label>
<input id="age" title="Please enter your age in years">

<script>
  $(function () {
    $(document).tooltip();
  });
</script>

Tooltip Options

Override 'content' as a function to generate dynamic tooltip HTML (e.g. from data attributes or AJAX). 'items' is a selector controlling which elements trigger tooltips. 'track: true' makes the tooltip follow the cursor — useful for detailed help text on diagrams.

jquery-ui
$(document).tooltip({
  content: function () {
    // Default: returns the element's title attribute
    return $(this).attr("title");
  },
  items: "[title]",       // which elements get tooltips
  position: { my: "left top+15", at: "left bottom" },
  show: { effect: "fadeIn", duration: 200 },
  hide: { effect: "fadeOut", duration: 200 },
  tooltipClass: "custom-tooltip",  // class for the tooltip div
  track: false,           // follow the mouse cursor
  disabled: false,
  close: null,            // (event defaults handle this)
});

Custom Content

The content function lets you build rich tooltips with HTML, images, or AJAX-fetched content. Return a string (HTML allowed). tooltipClass adds a custom class for styling. This is the standard pattern for thumbnail previews or help bubbles on form fields.

jquery-ui
<!-- HTML with data attributes -->
<a href="#" class="help" data-help="Click to save your changes">Save</a>
<a href="#" class="help" data-help="Undo the last action">Undo</a>

<script>
  $(".help").tooltip({
    content: function () {
      return "<strong>Help:</strong> " + $(this).data("help");
    },
    tooltipClass: "help-tooltip",
  });
</script>

<!-- With an image preview -->
$(".thumb").tooltip({
  content: function () {
    var src = $(this).attr("href");
    return "<img src='" + src + "' width='200'>";
  },
});

Tooltip Events

open and close fire as tooltips appear and disappear. The ui.tooltip property gives the tooltip element for customization. A common pattern is keeping the tooltip open while the user hovers over it — useful when the tooltip contains interactive content like links.

jquery-ui
$(".help").tooltip({
  open: function (event, ui) {
    // Tooltip just appeared
    ui.tooltip;  // the tooltip element
  },
  close: function (event, ui) {
    // Tooltip just disappeared
    ui.tooltip.one("transitionend", function () {
      // Cleanup after the hide animation
    });
  },
  create: function (event, ui) {
    // Widget initialized
  },
});

// Prevent tooltip from closing on hover
$(".help").tooltip({
  close: function (event, ui) {
    ui.tooltip.hover(
      function () { $(this).stop(true).fadeIn(); },
      function () { $(this).fadeOut(); }
    );
  },
});

Position & Methods

Position uses the jQuery UI Position utility: 'my' is the tooltip's anchor, 'at' is the target's anchor. collision handles edge cases — 'flip' moves to the other side if it would overflow. open()/close() show/hide tooltips programmatically, useful for validation errors.

jquery-ui
$("#target").tooltip({
  position: {
    my: "center top",       // tooltip's anchor point
    at: "center bottom",    // target's anchor point
    of: "#target",          // optional: position relative to this
    collision: "flip",      // "flip", "fit", "flipfit", "none"
    using: function (pos, feedback) {
      $(this).css(pos);
      console.log(feedback.horizontal, feedback.vertical);
    },
  },
});

// Methods
$("#target").tooltip("open");   // show programmatically
$("#target").tooltip("close");  // hide programmatically
$("#target").tooltip("disable");
$("#target").tooltip("enable");
$("#target").tooltip("widget");  // get the tooltip div
$("#target").tooltip("destroy");

Form Validation Tooltips

Tooltips are a clean way to show inline validation errors. Store the error message in a data attribute, set content to read it, and call open() to display. Returning false in the open handler prevents the tooltip when there's no error. Style with tooltipClass for red error styling.

jquery-ui
<!-- Show validation errors as tooltips -->
<form id="form">
  <input id="email" type="text" placeholder="Email">
  <input id="submit" type="submit" value="Submit">
</form>

<script>
  $("#form").tooltip({
    items: "input",
    content: function () {
      return $(this).data("error") || "";
    },
    position: { my: "left top", at: "left bottom+5" },
    tooltipClass: "error-tooltip",
    open: function (event, ui) {
      var el = $(event.originalEvent.target);
      if (!el.data("error")) return false;  // don't show if no error
    },
  });

  $("#submit").on("click", function (e) {
    var email = $("#email").val();
    if (!email.includes("@")) {
      e.preventDefault();
      $("#email").data("error", "Please enter a valid email")
                 .tooltip("open");
    }
  });
</script>
19

Effects

Core Effects

jQuery UI extends jQuery's show/hide/toggle with named effects and adds the .effect() method for non-hiding animations. Each accepts an options object, duration, and callback. 'transfer' creates a transfer element outline — useful for drag-to-cart animations.

jquery-ui
// Built-in effects (beyond jQuery's show/hide/toggle)
$("#box").hide("fade", {}, 1000);    // fade out
$("#box").show("slide", {}, 500);    // slide in
$("#box").toggle("explode", {}, 800); // explode toggle
$("#box").effect("bounce", { times: 3 }, 300);

// Available effect names:
// blind, bounce, clip, drop, explode, fade, fold,
// highlight, puff, pulsate, scale, shake, size, slide, transfer

Easing Functions

jQuery UI's effects core adds ~30 Robert Penner easing functions beyond jQuery's default 'swing' and 'linear'. Use them in any .animate() call, the easing option of show/hide/toggle, or as the third argument. 'easeOutBounce' and 'easeOutElastic' are popular for playful UIs.

jquery-ui
// jQuery core provides: swing (default), linear
// jQuery UI adds ~30 more easing functions
$("#box").animate({ width: 500 }, 1000, "easeInOutBounce");

// Available easings (subset):
// easeInQuad, easeOutQuad, easeInOutQuad
// easeInCubic, easeOutCubic, easeInOutCubic
// easeInQuart, easeOutQuart, easeInOutQuart
// easeInExpo, easeOutExpo, easeInOutExpo
// easeInBack, easeOutBack, easeInOutBack
// easeInBounce, easeOutBounce, easeInOutBounce
// easeInElastic, easeOutElastic, easeInOutElastic

Show/Hide/Toggle with Effects

Pass an effect name as the first argument to show/hide/toggle to animate. The second argument is an options object (direction, distance, percent, etc. depending on the effect). The third is duration; the fourth is a callback. Effects on hidden elements still work via show().

jquery-ui
// show with an effect
$("#box").show("drop", { direction: "left" }, 500);

// hide with an effect
$("#box").hide("puff", {}, 500);

// toggle with an effect
$("#box").toggle("scale", { percent: 0 }, 500);

// With a callback
$("#box").hide("blind", 500, function () {
  console.log("Animation complete");
});

// Direction option (where applicable)
$("#box").hide("slide", { direction: "up" });

Color Animation

jQuery core can't animate colors — jQuery UI's effects core adds this. backgroundColor, color, and borderColor become animatable. switchClass and toggleClass accept a duration to transition between classes smoothly, interpolating all the changed CSS properties.

jquery-ui
// jQuery UI extends animate() to support colors
$("#box").animate({
  backgroundColor: "#ff0000",
  color: "#ffffff",
  borderColor: "#000000",
}, 1000);

// Animate through the theme states
$("#box").animate(
  { backgroundColor: $.Color("#0a0") },
  { duration: 500 }
);

// Toggle class with smooth transitions
$("#box").switchClass("old-class", "new-class", 500);
$("#box").toggleClass("active", 500);  // duration = animated

Class Transitions

addClass, removeClass, and toggleClass gain an optional duration argument from jQuery UI — all CSS properties that differ between states animate smoothly. switchClass explicitly transitions between two classes. This is the cleanest way to animate between themed states.

jquery-ui
// Add/remove classes with animation
$("#box").addClass("highlight", 500);    // animate to new class
$("#box").removeClass("highlight", 500);
$("#box").toggleClass("highlight", 500);

// switchClass: smoothly transition from one class to another
$("#box").switchClass("state-default", "state-active", 500);

// All accept a callback
$("#box").addClass("expanded", 500, function () {
  console.log("Done expanding");
});

Effect Methods Reference

.effect() applies a named effect without changing visibility (shake, bounce, pulsate are pure effects). .transfer() animates a box outline from one element to another — classic for 'add to cart' feedback. Per-property easing arrays let different properties use different easings.

jquery-ui
// .effect() — run an effect without hiding
$("#box").effect("shake", { times: 3 }, 300);

// .transfer() — animate a transfer outline to another element
$("#product").effect("transfer", { to: "#cart" }, 500);

// .animate() with colors and easing
$("#box").animate({ left: 200, opacity: 0.5 }, "slow", "easeOutBounce");

// Custom animation with step
$("#box").animate({
  width: ["toggle", "swing"],   // [value, easing] per property
  height: ["toggle", "linear"],
}, 1000);
20

ThemeRoller

ThemeRoller Basics

ThemeRoller is the official web app for building custom jQuery UI themes. Adjust colors, fonts, corner radius, and textures with live preview, then download a ZIP with the themed CSS and image sprites. Prebuilt themes (smoothness, ui-lightness, etc.) are also available on the CDN.

jquery-ui
<!-- Use a prebuilt theme from the CDN -->
<link rel="stylesheet"
      href="https://code.jquery.com/ui/1.13.2/themes/smoothness/jquery-ui.css">

<!-- Or a custom theme from ThemeRoller (jqueryui.com/themeroller) -->
<!-- 1. Visit the ThemeRoller app -->
<!-- 2. Customize colors, fonts, corner radius, etc. -->
<!-- 3. Download the generated CSS file -->
<link rel="stylesheet" href="my-custom-theme/jquery-ui.css">

CSS Framework Classes

The CSS framework is independent of the JavaScript widgets — use ui-widget, ui-widget-header, ui-widget-content, and the state classes (ui-state-default, ui-state-hover, ui-state-active) in your own markup to match jQuery UI styling without any widget initialization.

jquery-ui
<!-- The jQuery UI CSS framework is reusable for custom markup -->
<div class="ui-widget">
  <div class="ui-widget-header ui-corner-top">
    <h3>Panel Header</h3>
  </div>
  <div class="ui-widget-content ui-corner-bottom">
    <p>Panel content with themed styling.</p>
    <button class="ui-button ui-widget ui-state-default ui-corner-all">
      <span class="ui-icon ui-icon-gear"></span> Action
    </button>
  </div>
</div>

Theme Variables & Structure

Every theme defines the same set of classes with different colors and textures. ui-state-highlight (yellow) is for notices; ui-state-error (red) for errors. The corner classes (ui-corner-all, ui-corner-top, etc.) make border-radius themable — ThemeRoller sets them all at once.

jquery-ui
/* ThemeRoller generates CSS with these key classes */
.ui-widget {
  font-family: Arial, sans-serif;   /* font family */
  font-size: 1em;                    /* base font size */
}
.ui-widget-content { border: 1px solid #aaa; background: #fff; color: #222; }
.ui-widget-header  { border: 1px solid #aaa; background: #ccc; color: #222; }
.ui-state-default  { border: 1px solid #d3d3d3; background: #e6e6e6; }
.ui-state-hover    { border: 1px solid #999;    background: #dadada; }
.ui-state-active   { border: 1px solid #aaa;    background: #fff; }
.ui-state-focus    { border: 1px solid #999;    background: #dadada; }
.ui-state-highlight { border: 1px solid #fcefa1; background: #fbf9ee; }
.ui-state-error     { border: 1px solid #cd0a0a; background: #fef1ec; }
.ui-corner-all { border-radius: 4px; }  /* themable radius */

Custom Theme Override

Load a base theme then override with higher-specificity CSS. This is faster than re-running ThemeRoller for small tweaks. Target the framework classes (ui-widget-header, ui-state-default, etc.) to restyle all widgets at once. Remove the corner radius for a flat, modern look.

jquery-ui
/* Load the base theme first */
@import url("https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css");

/* Override specific elements */
.ui-widget-header {
  background: linear-gradient(to bottom, #2c3e50, #34495e);
  color: #ecf0f1;
}
.ui-state-default {
  background: #3498db;
  border-color: #2980b9;
  color: #fff;
}
.ui-state-hover { background: #2980b9; }
.ui-state-active { background: #1abc9c; border-color: #16a085; }
.ui-corner-all { border-radius: 0; }  /* sharper look */

Theme Switching at Runtime

To switch themes at runtime, load multiple theme CSS files and toggle their 'disabled' property — only the enabled one applies. Persist the choice in localStorage. The widgets immediately pick up the new styling. For a single-CSS solution, swap the href attribute instead.

jquery-ui
<!-- Two theme stylesheets; toggle the disabled attribute -->
<link id="theme-light" rel="stylesheet"
      href="themes/ui-lightness/jquery-ui.css">
<link id="theme-dark" rel="stylesheet"
      href="themes/ui-darkness/jquery-ui.css" disabled>

<script>
  function switchTheme(name) {
    $("#theme-light").prop("disabled", name !== "light");
    $("#theme-dark").prop("disabled", name !== "dark");
    localStorage.setItem("theme", name);
  }

  // Restore on load
  $(function () {
    var saved = localStorage.getItem("theme") || "light";
    switchTheme(saved);
  });
</script>

Theming Specific Widgets

Target widget-specific classes (ui-datepicker, ui-dialog, ui-accordion-header) to restyle individual widgets without affecting others. The 1.12+ 'classes' option is cleaner — it adds custom classes to specific internal elements, which you style in your CSS. Use it instead of global overrides when possible.

jquery-ui
/* Datepicker: style the calendar popup */
.ui-datepicker {
  box-shadow: 0 4px 12px rgba(0,0,0,0.2);
  border-radius: 0;
}
.ui-datepicker .ui-state-highlight { /* today */ background: #ffd; }
.ui-datepicker .ui-state-active {    /* selected */ background: #2c3e50; }

/* Dialog: remove the default rounded corners */
.ui-dialog { border-radius: 0; box-shadow: 0 8px 30px rgba(0,0,0,0.3); }

/* Accordion: modernize the headers */
.ui-accordion .ui-accordion-header {
  background: #f5f5f5;
  border: none;
  border-bottom: 1px solid #ddd;
  font-weight: bold;
}

/* Use the 'classes' option (1.12+) for per-widget theming */
$("#dialog").dialog({
  classes: { "ui-dialog": "my-dialog", "ui-dialog-titlebar": "my-title" },
});

Was this helpful?

Learning path

Learn from scratch

Learn this language from the ground up with structured lessons.