Getting Started
Including jQuery
Include jQuery via a CDN for fast, cached loading. The minified version (.min.js) is for production; the uncompressed version is for debugging. Always provide a local fallback in case the CDN is unreachable. With npm, you can import jQuery as a module — useful for bundlers like Webpack/Vite. jQuery 3.7.x is the current line; older IE is no longer supported.
<!-- Production (CDN, minified) -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<!-- Development (CDN, uncompressed) -->
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<!-- Fallback: load local if CDN fails -->
<script>
window.jQuery || document.write(
'<script src="js/jquery-3.7.1.min.js"><\/script>'
)
</script>
<!-- npm install -->
<!-- npm install jquery -->Document Ready
Wrap DOM-manipulating code in $(document).ready() so it runs only after the DOM tree is parsed (don't wait for images). $(fn) is the shorthand. If your <script> is at the end of <body>, the DOM is already available and you can skip ready. jQuery's ready is similar to DOMContentLoaded — it fires before window.load (which waits for images/iframes).
// run code after DOM is fully parsed
$(document).ready(function () {
console.log('DOM ready')
})
// shorter equivalent
$(function () {
console.log('DOM ready')
})
// modern preferred (no ready needed at end of body)
// <script> at the end of <body> runs after DOM exists
// pass a function to $ — jQuery treats it as ready handler
$(function () {
$('.btn').on('click', function () {
alert('clicked')
})
})The jQuery Object ($)
$ is just an alias for jQuery — both work identically. As a function, $ selects elements (returns a jQuery collection). As a namespace, $.foo provides utility methods. If another library uses $, call $.noConflict() to release it; you can still use jQuery or pass $ into a ready callback to alias it locally.
// $ is an alias for jQuery
console.log($ === jQuery) // true
// $ as a function: select elements
$('p') // all paragraphs
$('#main') // element with id main
$('.btn.primary') // elements with class btn and primary
// $ as a namespace: utility methods
$.each([1, 2, 3], function (i, v) { console.log(i, v) })
$.extend({}, defaults, options)
$.type([]) // 'array'
// noConflict: release $ back to other libraries
$.noConflict()
jQuery(function ($) { /* $ available here */ })Chaining Methods
Most jQuery methods return the same jQuery collection, so you can chain calls — jQuery's signature feature. Use .end() to pop back to the previous set after a traversal method (.find(), .filter()). Indentation makes chained traversals readable. Avoid overly long chains — they become hard to debug. For non-chainable methods (like .width() getter), the chain breaks because they return a value, not the collection.
// most methods return the jQuery object, enabling chains
$('.box')
.addClass('active')
.css('color', 'red')
.slideDown(300)
.text('Hello')
// break across lines for readability
$('#nav')
.find('.item')
.addClass('highlight')
.end()
.find('.link')
.attr('target', '_blank')
// .end() pops the current filter back to previous setNo-Conflict Mode
$.noConflict() returns control of $ to whichever library defined it first. After calling, use the full jQuery name, or assign jQuery to a custom variable. The IIFE pattern (function($){...})(jQuery) is the classic way to keep $ as a local alias inside your module while leaving the global $ for other libraries — essential in WordPress and legacy environments.
// release $ to other libraries (e.g., Prototype)
$.noConflict()
// use jQuery full name
jQuery('.btn').on('click', function () { /* ... */ })
// or assign jQuery to a custom alias
const jq = $.noConflict()
jq('.btn').hide()
// IIFE pattern: keep $ inside a local scope
(function ($) {
$('.btn').on('click', function () { /* ... */ })
})(jQuery)Selectors
Basic Selectors
jQuery uses CSS selectors (mostly compatible with querySelectorAll). The big three: tag name, #id, .class. Comma combines selectors (union). #id is the fastest (uses getElementById). Universal * is slow — avoid it on large documents. Selector results are always a jQuery collection (array-like), even if 0 or 1 elements match.
// element selector
$('div') // all <div> elements
$('p') // all <p> elements
// id selector
$('#header') // element with id="header"
// class selector
$('.btn') // all elements with class="btn"
$('.btn.primary') // .btn AND .primary
// multiple (comma = OR)
$('div, p, .btn') // divs, paragraphs, and .btn
// universal
$('*') // all elements (slow — avoid)Hierarchy & Combinators
Combinators describe relationships: space (descendant), > (direct child), + (adjacent sibling), ~ (general sibling). Right-to-left evaluation means $('ul li') finds all <li> first, then filters to those inside <ul> — so specific right-side selectors perform better. Avoid deep combinators on huge documents; scope to a container via $(container).find(...) for better perf.
// descendant: space (any depth)
$('ul li') // <li> anywhere inside <ul>
// child: > (direct children only)
$('ul > li') // <li> directly inside <ul>
// adjacent sibling: + (immediately next)
$('h2 + p') // <p> right after <h2>
// general sibling: ~ (all following siblings)
$('h2 ~ p') // all <p> siblings after <h2>
// multiple levels
$('#nav .item > a span')Attribute Selectors
Attribute selectors target elements by attribute values: [attr] (presence), [attr=val] (exact), [attr^=val] (starts), [attr$=val] (ends), [attr*=val] (contains), [attr~=val] (word). Quote values for safety. [attr!=val] is a jQuery-only extension (use .not('[attr=val]') for CSS compliance). Useful for forms (input types), links (href patterns), and data-* attributes.
// has attribute
$('[href]') // any element with href
$('[data-id]') // any element with data-id
// exact value
$('[type="text"]') // type="text"
$('[href="https://example.com"]')
// substring matches
$('[href^="https"]') // starts with "https"
$('[href$=".pdf"]') // ends with ".pdf"
$('[href*="example"]') // contains "example"
// whitespace-separated word
$('[class~="active"]') // class contains word "active"
// inequality (jQuery extension, not CSS)
$('[href!="https://x.com"]')Form & Input Selectors
Form pseudo-selectors (:input, :text, :checked, etc.) are jQuery extensions — not part of CSS, so they can't use querySelectorAll's fast path. For performance on large forms, use $('input[type=text]') instead of $(':text'). :checked and :selected are essential for reading form state. These are dynamic — they re-evaluate on each access.
// :input matches all form controls
$(':input') // input, textarea, select, button
// by type
$(':text') // <input type="text">
$(':password')
$(':checkbox')
$(':radio')
$(':submit')
$(':file')
// by state
$(':checked') // checked checkbox/radio or selected option
$(':selected') // selected <option>
$(':disabled')
$(':enabled')
$(':focus')
// combined with class
$('input.required:visible')Filter & Content Selectors
Filters narrow a selection: :first/:last, :even/:odd (0-indexed), :eq(n), :gt(n), :lt(n). Content filters (:contains, :has, :empty, :parent) match based on contents. :visible and :hidden are based on offsetWidth/Height and CSS (note: elements with visibility:hidden are :hidden in jQuery 3+; they used to be :visible). Many of these are jQuery extensions — prefer .filter(), .first(), .eq() methods for better performance.
// basic filters
$('li:first') // first <li>
$('li:last') // last <li>
$('li:even') // even-indexed (0, 2, 4...)
$('li:odd') // odd-indexed
$('li:eq(2)') // 3rd <li> (0-indexed)
$('li:gt(2)') // <li> after index 2
$('li:lt(2)') // <li> before index 2
// content filters
$('div:contains("Hello")') // divs containing text "Hello"
$('div:empty') // divs with no children
$('div:has(p)') // divs containing <p>
$('div:parent') // divs that have children
// visibility
$(':visible')
$(':hidden')Events
Binding Events with .on()
.on() is the modern, all-in-one event binder (replacing .bind/.delegate/.live). Pass event name(s) and a handler. 'this' inside the handler is the DOM element (not jQuery-wrapped — wrap with $(this) if needed). Use event namespaces (click.myapp) to unbind specific handlers without affecting others. Multiple events can share one handler (space-separated) or have separate handlers (object form).
// basic binding
$('.btn').on('click', function (e) {
console.log('clicked!', this) // 'this' is the DOM element
})
// multiple events, same handler
$('.box').on('mouseenter mouseleave', function () {
$(this).toggleClass('hover')
})
// multiple events, different handlers
$('.input').on({
focus: function () { $(this).addClass('focused') },
blur: function () { $(this).removeClass('focused') }
})
// named events (for targeted unbinding)
$('.btn').on('click.myapp', handler)
$('.btn').off('click.myapp') // only removes this oneEvent Delegation
Event delegation binds one handler to a parent that catches events from children via bubbling. The second selector to .on() ('li') filters which children trigger the handler. Benefits: one handler instead of N, automatic support for dynamically added elements, lower memory. Essential for long lists or SPAs. 'this' is the matched child (the li), not the parent. Use e.delegateTarget to access the parent.
// delegate: handle events on children, now or future
$('#list').on('click', 'li', function (e) {
// 'this' is the <li> that was clicked
$(this).toggleClass('done')
})
// works for <li> added AFTER binding too
$('#list').append('<li>New item (also clickable)</li>')
// WHY: instead of binding to each <li>,
// bind ONCE to the parent; clicks bubble up
// - 1 handler instead of N
// - works for dynamically added elements
// - lower memory, faster setupEvent Object & Methods
The event object (e) carries info and control methods. preventDefault stops the browser default (link navigation, form submit). stopPropagation stops bubbling; stopImmediatePropagation also stops other handlers on the same element. e.target is the actual clicked element (may be a child); e.currentTarget is the element with the handler (= this). Pass data to handlers via the optional second arg to .on().
$('.link').on('click', function (e) {
e.preventDefault() // stop default action (e.g., navigation)
e.stopPropagation() // stop bubbling to parents
e.stopImmediatePropagation() // stop other handlers on same element
console.log(e.type) // 'click'
console.log(e.target) // the actual clicked element
console.log(e.currentTarget) // the element with the handler (= this)
console.log(e.which) // mouse button or key code
console.log(e.pageX, e.pageY) // mouse coordinates
// data passed via .on(name, data, handler)
})
$('.btn').on('click', { greeting: 'hi' }, function (e) {
console.log(e.data.greeting) // 'hi'
})Shorthand Event Methods
Shorthand methods (.click, .focus, .submit, etc.) bind a handler when called with a function, or trigger the event when called without. .hover(enter, leave) is a convenience for mouseenter+mouseleave. These are equivalent to .on('event', fn) but shorter. Some shorthands (.load, .error) were removed in jQuery 3 — use .on('load', ...) instead. Prefer .on() for new code; it's more explicit and supports delegation.
// shorthand: bind a handler (or trigger if no handler)
$('.btn').click(function () { /* ... */ })
$('.btn').click() // trigger click
// common shorthands
$('.box').hover(enterFn, leaveFn) // mouseenter + mouseleave
$('.input').focus(function () { /* ... */ })
$('.input').blur(function () { /* ... */ })
$('.form').submit(function (e) {
e.preventDefault()
/* ... */
})
$('.el').mouseenter(fn).mouseleave(fn).mousemove(fn)
$(window).resize(fn).scroll(fn)
// deprecated: .load(), .unload(), .error() (removed in jQuery 3)Triggering & One-Time Events
.trigger('event') fires handlers AND native behavior (e.g., navigation); .triggerHandler() fires only jQuery-bound handlers and returns the handler's return value (not chainable). .one() binds a handler that auto-removes after the first invocation — perfect for first-click hints, one-time setup. Custom events let components communicate: $(document).trigger('myapp:ready') and listeners subscribe with .on('myapp:ready', fn).
// trigger an event programmatically
$('.btn').trigger('click')
$('.btn').click() // shorthand
// trigger with extra data
$('.box').trigger('custom', [1, 2, 3])
// custom events
$('.box').on('custom', function (e, a, b, c) {
console.log(a, b, c) // 1 2 3
})
// fire handler only once
$('.btn').one('click', function () {
alert('This fires only once')
})
// trigger only native handlers, not custom
$('.link').triggerHandler('click')DOM Manipulation
Get & Set Content
.html() works with HTML markup (like innerHTML) — tags are parsed. .text() is for plain text — tags are escaped and shown literally (safer against XSS for user input). .val() is for form controls (input, select, textarea). All three are getters (return the first element's value) when called with no arg, and setters (apply to all matched elements) when called with an arg. Setters accept a callback (index, oldValue) => newValue.
// .html(): get or set HTML content
$('#box').html() // get innerHTML
$('#box').html('<p>Hello</p>') // set innerHTML
// .text(): get or set text (HTML-escaped)
$('#box').text() // get text content
$('#box').text('<p>Not parsed</p>') // displays literally
// setter with callback (index, old value)
$('p').text(function (i, oldText) {
return i + ': ' + oldText
})
// .val(): form value
$('input').val() // get
$('input').val('new value') // set
$('select').val() // get selected value
$('select').val(['a', 'b']) // multi-selectInserting Elements
Create elements by passing HTML to $(): $('<div class="x">...</div>'). Append/prepend insert inside (at end/beginning); before/after insert outside (as siblings). The 'To' variants (appendTo, prependTo, insertBefore, insertAfter) reverse the subject — useful for chaining on the new element. Newly inserted elements inherit event handlers if bound via delegation, but not if bound directly before insertion.
// create new element
const $li = $('<li class="item">New item</li>')
// add as last child of each matched element
$('ul').append($li)
$('ul').append('<li>Direct string</li>')
// add as first child
$('ul').prepend('<li>First</li>')
// insert before/after matched elements
$('.box').before('<hr>')
$('.box').after('<hr>')
// reverse direction (insert target into container)
$('<p>Hi</p>').appendTo('#main') // same as $('#main').append(...)
$('<p>Hi</p>').insertBefore('#nav')Removing & Replacing
.remove() deletes elements and cleans up their data/events. .detach() removes from DOM but preserves data/events — useful for temporarily relocating elements. .empty() clears children but keeps the element. .replaceWith() swaps each element with new content. .unwrap() removes the parent, promoting the element up. Always use .remove() or .detach() — never just .html('') on a parent, which leaks data/events on children.
// remove element (and its data + events)
$('.box').remove()
// detach: remove but keep events/data (for re-insertion)
const $el = $('.box').detach()
// ... later
$('body').append($el) // events still work
// empty: remove all children (keep element)
$('.box').empty()
// replace with new content
$('.old').replaceWith('<div class="new">New</div>')
// unwrap: remove parent (keep element)
$('.box').unwrap()Wrapping & Cloning
.wrap() wraps each element individually; .wrapAll() wraps the whole set as one group; .wrapInner() wraps the contents (not the element itself). .clone() creates a deep copy — pass true to also clone event handlers and data (default false, so handlers don't fire on the copy). .unwrap() removes the immediate parent. These are powerful for restructuring markup without rewriting HTML strings.
// wrap each element in a structure
$('p').wrap('<div class="wrapper"></div>')
// each <p> becomes <div class="wrapper"><p>...</p></div>
// wrap all matched elements together
$('p').wrapAll('<div class="all"></div>')
// wrap inner contents
$('p').wrapInner('<span></span>')
// <p><span>...</span></p>
// clone (with events)
const $copy = $('.box').clone(true) // true = clone events too
$('body').append($copy)
// unwrap (remove wrapper)
$('.box').unwrap()Iterating & Filtering
.each() iterates — 'this' is the raw DOM element; return false to break, anything else to continue. .map() transforms to a new jQuery collection; call .get() to convert to a plain array. .filter() narrows by selector or callback; .not() is the inverse. .is() returns a boolean (does any element match?) — useful for conditionals. Avoid for loops with .eq(i); use .each() or .map() for idiomatic jQuery.
// .each: iterate (this = DOM element, i = index)
$('li').each(function (i, el) {
console.log(i, this, el) // el === this
if (i === 2) return false // break
// return true to continue
})
// .map: transform to new array
const ids = $('li').map(function (i, el) {
return $(el).data('id')
}).get() // .get() converts to plain array
// .filter: keep matching
$('li').filter('.active').addClass('on')
$('li').filter(function (i) { return i % 2 === 0 })
// .not: remove matching
$('li').not('.active').addClass('off')
// .is: returns boolean (does ANY match?)
if ($('li').is('.active')) { /* at least one is active */ }CSS Manipulation
Get & Set CSS Properties
.css() gets computed styles (always the resolved value, even from CSS rules) or sets inline styles. For getters, pass a single property name (returns a string). For setters, pass (prop, value), or an object of prop:value pairs. Property names can be camelCase or kebab-case (the latter needs quotes). Numeric values default to pixels for most properties. Avoid .css() for layout — use classes and stylesheets for maintainability.