Pages change while people use them: a new message appears in a chat, a product is added to the cart, a search returns fresh results. In this lesson you will learn to add and remove elements with jQuery: create new ones, put them exactly where you want, and take them away again – without opening the door to security problems.
Creating new elements
Pass an HTML tag to $() and jQuery creates a new, detached element – it exists in memory but is not on the page yet. You can then set its text and attributes with the methods you already know from jQuery Get and Set Content, or pass them as an object in the second argument.
// 1. Create, then set content safely with .text()
const $item = $('<li>').text(userInput).addClass('item');
// 2. Tag plus an object of properties (also safe for text)
const $link = $('<a>', { href: '/learn/jquery/', text: 'jQuery track', 'class': 'nav-link' });
// 3. A full HTML string – only for markup you wrote yourself
const $badge = $('<span class="badge">New</span>');
// Plain JavaScript equivalent of #1
const li = document.createElement('li');
li.textContent = userInput;
li.classList.add('item');Watch out: Never build HTML by joining strings with user data, as in $('<li>' + name + '</li>'). If name contains markup, it becomes real HTML on your page (an XSS risk). Create the element first and put the data in with .text() or the text property.
Inserting elements
Four methods cover every position. Two put content inside the target element, two put it next to it:
| Method | Where the new content goes | Plain JavaScript |
|---|---|---|
$(target).append(x) | Inside, at the end | target.append(x) |
$(target).prepend(x) | Inside, at the start | target.prepend(x) |
$(target).after(x) | Outside, right after the target | target.after(x) |
$(target).before(x) | Outside, right before the target | target.before(x) |
Each also has a reversed twin that starts from the new content: $item.appendTo('#list') does the same as $('#list').append($item), but returns $item, which is handy for chaining more calls on the new element. The others are .prependTo(), .insertAfter() and .insertBefore().
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>A shopping list: append, prepend and remove</title>
<style>
body { font-family: system-ui, sans-serif; padding: 16px; line-height: 1.5; }
li { margin: 4px 0; }
li.urgent { color: #b91c1c; font-weight: bold; }
.del { margin-left: 8px; }
</style>
</head>
<body>
<form id="add-form">
<label for="item">Item</label>
<input id="item" type="text" value="Coconut oil">
<label><input id="urgent" type="checkbox" checked> Urgent</label>
<button type="submit">Add</button>
</form>
<ul id="list">
<li>Rice 5 kg <button type="button" class="del">Remove</button></li>
</ul>
<button id="clear" type="button">Clear list</button>
<p id="status" role="status"></p>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $list = $('#list');
function showCount() {
const n = $list.children().length;
$('#status').text(n ? `${n} item(s)` : 'The list is empty.');
}
$('#add-form').on('submit', (event) => {
event.preventDefault();
const name = $('#item').val().trim();
if (!name) return;
const $li = $('<li>').text(name + ' ');
$('<button>', { type: 'button', 'class': 'del', text: 'Remove' }).appendTo($li);
if ($('#urgent').prop('checked')) {
$li.addClass('urgent').prependTo($list); // urgent items go to the top
} else {
$list.append($li);
}
$('#item').val('').trigger('focus');
showCount();
});
// Delegated, so it works for new items too
$list.on('click', '.del', (event) => {
$(event.currentTarget).closest('li').remove();
showCount();
});
$('#clear').on('click', () => {
$list.empty();
showCount();
});
showCount();
</script>
</body>
</html>A few details in this demo are worth copying. The new item’s text is set with .text(), so typing <b>Ghee</b> shows the tags instead of creating bold text. The Remove buttons use event delegation from jQuery Events, so items added later can be removed too. After adding, focus returns to the text box, so the next item can be typed straight away.
Tell screen readers when you add and remove elements
Sighted users notice when a new item appears; people using a screen reader may not. The count paragraph has role="status", which makes it a polite live region: when its text changes, screen readers read the new text out without moving focus. Use one short live region for messages like “3 items” or “Item removed” rather than making large parts of the page live.
Tip: If you insert an element that is already on the page, jQuery moves it rather than copying it. That makes “move this card to the Done column” a one-liner: $card.appendTo('#done'). To insert a copy instead, use .clone() first.
Removing elements: remove, detach and empty
.remove()takes the elements off the page and also cleans up their jQuery event handlers and data. Use it when the element is gone for good..detach()takes them off the page but keeps handlers and data, so you can put the same element back later..empty()keeps the element itself and removes everything inside it – perfect for clearing a list before redrawing it.
Two more helpers are worth knowing. .replaceWith(newContent) swaps an element for something else, for example a “Loading…” message for the real results. .clone() copies an element; .clone(true) also copies its jQuery event handlers. Watch out for duplicate id attributes when cloning.
Building a list from data
A common job is turning an array of objects – often from a server – into rows or cards. Build each element with .text(), collect them in an array, then add them all with a single .append(). One insertion means the browser recalculates the layout once instead of once per row.
You will often see older code that builds one long HTML string in a loop and then calls .html() once. It is fast, but every value in the string is parsed as markup, so a train name containing < or a quote can break the table – or worse. Creating elements and using .text() costs a few more lines and removes that whole class of bugs.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Rendering an array into a table</title>
<style>
body { font-family: system-ui, sans-serif; padding: 16px; line-height: 1.5; }
table { border-collapse: collapse; margin-top: 8px; }
th, td { border: 1px solid #ccc; padding: 6px 10px; text-align: left; }
</style>
</head>
<body>
<table>
<thead><tr><th>Train</th><th>From</th><th>To</th></tr></thead>
<tbody id="trains"></tbody>
</table>
<p id="note"></p>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const trains = [
{ name: 'Vaigai Express', from: 'Madurai', to: 'Chennai Egmore' },
{ name: 'Brindavan Express', from: 'Chennai Central', to: 'Bengaluru' },
{ name: 'Puducherry Express', from: 'Puducherry', to: 'Mangaluru' }
];
const rows = trains.map((t) =>
$('<tr>').append(
$('<td>').text(t.name),
$('<td>').text(t.from),
$('<td>').text(t.to)
)
);
$('#trains').empty().append(rows); // one insert for all rows
$('#note').text(`Showing ${rows.length} trains.`);
</script>
</body>
</html>