jQuery to JavaScript Converter
Convert legacy jQuery calls, selectors, events, and manipulations into high-performance, native vanilla ES6+ JavaScript.
Comprehensive Guide to Migrating from jQuery to Vanilla JavaScript
For over a decade, jQuery served as the foundational utility belt for web developers. It solved the pain points of cross-browser DOM discrepancies, simplified Ajax network calls, and enabled clean animation controls. However, the web has evolved significantly. Modern browsers natively support robust W3C Selector APIs, class list helpers, and high-performance asynchronous modules that run natively without requiring a bulky library wrapper.
Why Migrate to Vanilla JavaScript?
Each external library loaded on a webpage increases the overall payload size, affecting speed scores such as Largest Contentful Paint (LCP) and First Input Delay (FID). Removing jQuery removes a network payload from your server and speeds up execution times. Native JavaScript runs directly inside the browser's V8 engine, rendering animations and event listeners at hardware-accelerated speeds.
Basic Concepts: Replicating jQuery's Chainable Shell
The jQuery library uses a wrapper function $() that returns a customized object containing selected DOM elements alongside a chain of built-in methods. This wrapper pattern is called a chainable shell. We can implement a clean, lightweight version of this design in native modern JavaScript using a class shell. Once defined, you can chain selectors and styles just like jQuery, but with native browser speed.
Here is how a clean, native ES6 Utils class wrapper is structured to mimic standard jQuery selection, element mapping, and chainable actions:
export class Utils {
constructor(selector) {
this.elements = Utils.getSelector(selector);
this.element = this.get(0);
return this;
}
get(index) {
return this.elements[index] || null;
}
static getSelector(selector, context = document) {
if (typeof selector !== 'string') {
return selector;
}
if (selector.startsWith('#') && !selector.includes(' ') && !selector.includes('.')) {
return [document.getElementById(selector.substring(1))];
}
return Array.from(context.querySelectorAll(selector));
}
each(func) {
if (!this.elements || this.elements.length === 0) {
return this;
}
this.elements.forEach((el, index) => {
func.call(el, el, index);
});
return this;
}
}
List of Available jQuery Alternative Methods in Vanilla JS
Below is a detailed guide of native JavaScript methods that can completely replace legacy jQuery calls. These alternatives use modern Web APIs and provide highly responsive operations.
1. Selection and Querying
The query selectors querySelector and querySelectorAll allow matching elements using standard CSS syntax. Unlike jQuery, which wraps results in a custom object array, querySelectorAll returns a static NodeList which can be converted to a standard JavaScript array using Array.from().
- jQuery:
const items = $('.box'); - Vanilla JS:
const items = document.querySelectorAll('.box');
2. Class Manipulation (addClass / removeClass / toggleClass)
Modern browser elements feature a native classList object. This property provides simple helpers to add, remove, toggle, or check classes without manually parsing string attributes.
// addClass alternative
addClass(classNames = '') {
this.each((el) => {
classNames.split(' ').forEach((className) => {
if (className.trim()) el.classList.add(className.trim());
});
});
return this;
}
// removeClass alternative
removeClass(classNames = '') {
this.each((el) => {
classNames.split(' ').forEach((className) => {
if (className.trim()) el.classList.remove(className.trim());
});
});
return this;
}
3. DOM Insertion (append / prepend)
Instead of relying on custom parsers, modern browsers provide standard DOM insertion helpers like appendChild for node parameters, and insertAdjacentHTML for string inputs. The latter is incredibly performant as it parses strings directly into HTML elements without destroying existing DOM nodes.
append(html) {
this.each((el) => {
if (typeof html === 'string') {
el.insertAdjacentHTML('beforeend', html);
} else {
el.appendChild(html);
}
});
return this;
}
4. Attribute Configuration (attr)
Reading or setting element properties is handled natively using getAttribute and setAttribute methods. This is cleaner than jQuery's unified attr method, as it splits reads and writes into explicit, predictable calls.
attr(name, value) {
if (value === undefined) {
if (!this.element) return '';
return this.element.getAttribute(name);
}
this.each((el) => {
el.setAttribute(name, value);
});
return this;
}
5. Element Styling (css)
Modifying styles inline is handled directly via the element's style object. To fetch computed values (such as tracking active dimensions set by an external stylesheet), use the standard window.getComputedStyle(element) method.
css(css, value) {
if (value !== undefined) {
this.each((el) => {
el.style[css] = value;
});
return this;
}
if (typeof css === 'object') {
this.each((el) => {
for (const property in css) {
el.style[property] = css[property];
}
});
return this;
}
if (this.element) {
return window.getComputedStyle(this.element)[css];
}
return '';
}
6. Selecting Sibling Elements (siblings)
In jQuery, $(selector).siblings() returns all sibling nodes. In native JavaScript, this is achieved by navigating to the element's parent container (parentNode), reading all child nodes (children), and filtering out the target node itself.
siblings() {
if (!this.element) return new Utils([]);
const parent = this.element.parentNode;
if (!parent) return new Utils([]);
const siblingsList = Array.from(parent.children).filter(child => child !== this.element);
return new Utils(siblingsList);
}
Frequently Asked Questions about jQuery Migration
Is jQuery completely obsolete?
While jQuery is not actively used in most new framework-based projects (like React, Vue, or Svelte), it remains present on millions of legacy websites. If you are building a greenfield site, it is best to avoid adding jQuery to keep payloads lightweight.
Does WordPress still use jQuery?
Yes, WordPress core loads jQuery by default to support backwards compatibility for plugins and templates. However, developers are increasingly building theme structures using Gutenberg blocks and native Vanilla JS to improve PageSpeed metrics.
How do I handle event delegation on dynamically added elements?
In jQuery, you use $(parent).on('click', '.child', fn). In native JavaScript, you attach the event listener to the parent element, and inspect the target element inside the event callback:
document.getElementById('parent').addEventListener('click', (e) => {
if (e.target.matches('.child')) {
// execute click logic here
}
});
What is the native replacement for $.ajax?
The standard modern native tool is the Fetch API. Fetch is promise-based and handles response parsing natively:
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));