f in x
JavaScript DOM Manipulation Without jQuery — Efficient Vanilla JS for Developers
> cd .. / HUB_EDITORIALE
Sviluppo di siti web

JavaScript DOM Manipulation Without jQuery — Efficient Vanilla JS for Developers

[2026-06-28] Author: Ing. Calogero Bono
Zenithby Meteora Web Il sistema operativo della tua attività. Social, clienti, prenotazioni e fatture in un'unica piattaforma. Palestre, barber, professionisti. Scopri Zenith Demo gratis · senza carta

Still writing $('.element').hide()? That tiny jQuery snippet costs an HTTP request, extra parsing, and a function call that you can replace with a single line of native JavaScript. At Meteora Web, we see it every day in incoming projects: code that loads an 80KB library just to use three methods. Result? Slower pages, heavier bundles, and a waiting user. This guide shows you how to manipulate the DOM without jQuery, efficiently and modernly.

Why ditch jQuery for DOM manipulation?

jQuery was a game-changer when Internet Explorer ruled and the DOM API was a nightmare. Today, all modern browsers natively support querySelector, classList, addEventListener, and fetch. Keeping jQuery means:

  • Extra payload: even minified, jQuery is ~30KB compressed. For a site that must load in under two seconds, every kilobyte matters.
  • Dead dependencies: security updates, conflicts with other frameworks, unnecessary complexity.
  • Performance: native DOM operations are faster because they don't go through an abstraction layer.

An e-commerce client had a carousel using jQuery for slide animations. Replacing it with requestAnimationFrame and classList.toggle reduced touch interaction time by 40%. Not theory — numbers.

Sponsored Protocol

How to select DOM elements without jQuery?

The first thing you learn with jQuery is $('.class'). Native JavaScript gives you two main weapons.

querySelector and querySelectorAll

Use document.querySelector('.class') for the first element, document.querySelectorAll('.class') for all. They accept any CSS selector, just like jQuery.

// jQuery
$('.item').addClass('active');

// Native
document.querySelectorAll('.item').forEach(el => el.classList.add('active'));

Note: querySelectorAll returns a static NodeList — not live. If you add or remove elements after selection, it won't update automatically. For dynamic lists, select each time you need.

getElementById and getElementsByClassName

For maximum performance, document.getElementById('id') is still fastest. getElementsByClassName returns a live HTMLCollection (updates automatically).

// Fast for ID
const header = document.getElementById('header');

// Live for classes
const slides = document.getElementsByClassName('slide');
console.log(slides.length); // updates if you add a slide

How to efficiently modify classes and styles?

jQuery: $('.box').addClass('red'). Native: classList.add('red'). Simple, but details matter.

Sponsored Protocol

classList: add, remove, toggle, contains

const el = document.querySelector('.box');

// Add
el.classList.add('highlighted');

// Remove
el.classList.remove('hidden');

// Toggle
el.classList.toggle('active');

// Check
if (el.classList.contains('active')) {
  // do something
}

Watch out: classList does not accept space-separated class strings. To add multiple classes, pass multiple arguments: el.classList.add('a', 'b', 'c');.

Modifying inline styles

jQuery: $('.box').css('background', 'red');. Native:

el.style.background = 'red';
el.style.setProperty('--custom-prop', '10px');

For performance, avoid reading style inside loops. Read once, apply outside the loop. And prefer classes over inline styles: classes are more maintainable and leverage browser caching.

Sponsored Protocol

How to handle events without jQuery?

jQuery: $('.btn').on('click', fn). Native: addEventListener. But there's a trick many forget: event delegation.

Direct addEventListener

document.querySelector('.btn').addEventListener('click', function(e) {
  console.log('Clicked!');
});

To remove, removeEventListener requires the same function (not anonymous).

Event delegation for dynamic elements

If you have a changing list (e.g., comments loaded via AJAX), don't attach a listener to each new element. Use delegation:

// jQuery
$('#list').on('click', '.item', fn);

// Native
document.querySelector('#list').addEventListener('click', function(e) {
  const item = e.target.closest('.item');
  if (item) {
    // run action
  }
});

Benefits: single listener, works for elements added later. closest is key to traverse up to the right parent.

How to create and insert DOM elements without jQuery?

jQuery: $('<div>').text('Hello').appendTo('.container');. Native: document.createElement and appendChild or insertAdjacentHTML.

createElement + append

const div = document.createElement('div');
div.textContent = 'Hello';
div.classList.add('message');
document.querySelector('.container').appendChild(div);

// More modern: append (multiple nodes)
document.querySelector('.container').append(div, anotherNode, 'text');

insertAdjacentHTML for raw HTML

If you have an HTML string, insertAdjacentHTML is faster than innerHTML because it doesn't destroy existing listeners:

Sponsored Protocol

document.querySelector('.container').insertAdjacentHTML('beforeend', '<div class="new">Content</div>');

Positions: beforebegin, afterbegin, beforeend, afterend.

Common mistakes in native DOM manipulation?

When we take over inherited projects, we always find the same errors. Avoiding them means performance and maintainability.

  • Reading and writing DOM in loops: each DOM access is costly. Accumulate changes and apply once. Use DocumentFragment for multiple insertions.
  • Using innerHTML without sanitization: opens XSS. Prefer textContent for text, setAttribute for attributes.
  • Forgetting to remove listeners: creates memory leaks, especially in SPAs. Use AbortController to remove them in bulk.
  • Not using delegation: if you have 100 dynamic elements, don't attach 100 listeners. One is enough.

What to do now

  1. Audit your code: search for $() or jQuery in your project. Evaluate if you can replace each occurrence with native.
  2. Use a polyfill only if necessary: for old browsers, classList and querySelector are supported from IE10+. If you need IE9, consider a small polyfill instead of full jQuery.
  3. Measure performance: open DevTools, record DOM operations and compare before/after. Numbers will convince you.
  4. Learn closest and matches: they are the replacements for jQuery's parents() and is().

We at Meteora Web have gradually removed jQuery from all new projects for years. Not for fashion, but because native is more performant, lighter, and easier to maintain. If you're building a site today, there's no reason to load a legacy library. The DOM API is mature. Use it.

Sponsored Protocol

For the modern JavaScript context, check out our Pillar: Modern JavaScript ES2024+.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere informatico, fondatore di Meteora Web e Zenith OS. System administrator e progettista di piattaforme, app e CMS proprietari, con esperienza in sviluppo full-stack, marketing digitale ed ecosistema Google.
[ Read Full Dossier ]

> METEORA_WEB // DIGITAL AGENCY

We build the digital presence your business deserves.

Websites, social media, online advertising, e-commerce and high-performance hosting, engineered with method by computer engineers in Sciacca, for all of Italy.

> MW_JOURNAL

> READ_ALL()