Introduction
jQuery provides several ways to create new DOM elements dynamically. The most common is passing an HTML string to the $() function, which parses it and returns a jQuery object you can manipulate before inserting it into the page. You can also pass a plain tag string with a properties object for a cleaner, XSS-safe approach. Understanding both methods helps you choose the right one based on whether your content comes from user input or is hardcoded.
Basic Creation
1// Method 1: HTML string
2var newDiv = $('<div>');
3
4// Method 2: Self-closing tag
5var newDiv = $('<div/>');
6
7// Method 3: Full HTML string with content
8var newDiv = $('<div>Hello World</div>');
9
10// All three create a jQuery-wrapped div element
The created element exists in memory but is not yet part of the DOM — you must insert it explicitly.
Adding Attributes and Content
1// Chain methods after creation
2var card = $('<div>')
3 .attr('id', 'user-card')
4 .addClass('card shadow')
5 .css({ padding: '20px', margin: '10px' })
6 .text('Welcome back, Alice');
7
8// Append to the page
9$('#container').append(card);
Using the Properties Object
1// Pass attributes as a second argument — cleaner for multiple attributes
2var card = $('<div>', {
3 id: 'user-card',
4 class: 'card shadow',
5 text: 'Welcome back, Alice',
6 css: { padding: '20px', margin: '10px' },
7 click: function() {
8 alert('Card clicked!');
9 }
10});
11
12$('#container').append(card);
The properties object accepts any jQuery method name as a key — text, html, css, click, addClass, attr, etc.
Inserting into the DOM
1var newDiv = $('<div>').text('New content');
2
3// Append as the last child
4$('#container').append(newDiv);
5
6// Prepend as the first child
7$('#container').prepend(newDiv);
8
9// Insert after a specific element
10$('#existing-div').after(newDiv);
11
12// Insert before a specific element
13$('#existing-div').before(newDiv);
14
15// Replace an element
16$('#old-div').replaceWith(newDiv);
17
18// Wrap an element with the new div
19$('#content').wrap($('<div>').addClass('wrapper'));
Creating Complex Structures
1// Build nested elements
2var card = $('<div>').addClass('card').append(
3 $('<div>').addClass('card-header').append(
4 $('<h3>').text('User Profile')
5 ),
6 $('<div>').addClass('card-body').append(
7 $('<p>').text('Name: Alice'),
8 $('<p>').text('Role: Admin'),
9 $('<button>')
10 .addClass('btn btn-primary')
11 .text('Edit')
12 .on('click', function() {
13 console.log('Edit clicked');
14 })
15 )
16);
17
18$('#app').append(card);
From an HTML String
1// For complex HTML, a template string is often clearer
2var cardHtml = `
3 <div class="card">
4 <div class="card-header">
5 <h3>User Profile</h3>
6 </div>
7 <div class="card-body">
8 <p>Name: Alice</p>
9 <p>Role: Admin</p>
10 </div>
11 </div>
12`;
13
14var card = $(cardHtml);
15card.find('.card-body').append(
16 $('<button>').addClass('btn').text('Edit')
17);
18
19$('#app').append(card);
Creating Multiple Elements
1// Create a list from an array
2var items = ['Apple', 'Banana', 'Cherry', 'Date'];
3
4var list = $('<ul>').addClass('fruit-list');
5items.forEach(function(item) {
6 list.append($('<li>').text(item));
7});
8
9$('#container').append(list);
1// Using $.each
2var data = [
3 { name: 'Alice', age: 30 },
4 { name: 'Bob', age: 25 }
5];
6
7var table = $('<table>').addClass('table');
8var thead = $('<thead>').append(
9 $('<tr>').append(
10 $('<th>').text('Name'),
11 $('<th>').text('Age')
12 )
13);
14var tbody = $('<tbody>');
15
16$.each(data, function(i, row) {
17 tbody.append(
18 $('<tr>').append(
19 $('<td>').text(row.name),
20 $('<td>').text(row.age)
21 )
22 );
23});
24
25table.append(thead, tbody);
26$('#container').append(table);
For adding many elements, batch them to minimize DOM reflows:
1// SLOW: appends to DOM 1000 times
2for (var i = 0; i < 1000; i++) {
3 $('#list').append($('<li>').text('Item ' + i));
4}
5
6// FAST: build in memory, append once
7var fragment = $(document.createDocumentFragment());
8for (var i = 0; i < 1000; i++) {
9 fragment.append($('<li>').text('Item ' + i));
10}
11$('#list').append(fragment);
Vanilla JavaScript Equivalent
1// jQuery
2var div = $('<div>').attr('id', 'myDiv').text('Hello').appendTo('#container');
3
4// Vanilla JS equivalent
5var div = document.createElement('div');
6div.id = 'myDiv';
7div.textContent = 'Hello';
8document.getElementById('container').appendChild(div);
Common Pitfalls
XSS with .html() and user input: $('<div>').html(userInput) executes any script tags in the input. Use .text() for untrusted content, which escapes HTML entities automatically.
Created elements are detached: $('<div>') creates an element in memory. If you do not append/prepend/insert it into the DOM, it is never visible. Forgetting the insertion step is a common mistake.
Event handlers on dynamic elements: Events bound with .on('click', handler) on a dynamically created element only work after the element is in the DOM. Alternatively, use event delegation: $(document).on('click', '.dynamic-class', handler).
Duplicate IDs: Creating multiple elements with the same id attribute violates HTML spec and causes unpredictable behavior with $('#id') selectors. Use classes instead for repeated elements.
Performance with large HTML strings: Parsing large HTML strings with $(htmlString) is slower than building with document.createElement. For thousands of elements, use document fragments or virtual DOM libraries.
Summary
Use $('<div>') or $('<div>', { properties }) to create new elements
Chain .attr(), .addClass(), .css(), .text(), and .on() to configure before inserting
Insert with .append(), .prepend(), .after(), .before(), or .replaceWith()
Use .text() instead of .html() for user-provided content to prevent XSS
Batch DOM insertions with document fragments for better performance
Use event delegation for click handlers on dynamically created elements