434

Recently I've been doing a lot of modal window pop-ups and what not, for which I used jQuery. The method that I used to create the new elements on the page has overwhelmingly been along the lines of:

$("<div></div>");

However, I'm getting the feeling that this isn't the best or the most efficient method of doing this. What is the best way to create elements in jQuery from a performance perspective?

This answer has the benchmarks to the suggestions below.

Community
  • 1
  • 1
Darko
  • 38,310
  • 15
  • 80
  • 107
  • 1
    Experiment with removing styles too and see if that speeds things up. I find CSS application and updates slow things down the most on big pages for me. – CVertex Nov 29 '08 at 05:00
  • 3
    Beware of premature optimization -- if you're not doing this for hundreds of DOM elements at a time, or using VERY old browsers, then you're probably not going to notice any difference in the browser's performance. – Blazemonger Jul 31 '12 at 21:43
  • 1
    @Blazemonger It wasn't so much that I *needed* a more efficient method of creating DOM elements, but the situation that I was in made me ponder what the alternatives are and how efficient they might be. – Darko Aug 01 '12 at 04:27
  • **[jsperf stats](http://jsperf.com/jquery-vs-createelement)** – jantimon Feb 15 '13 at 17:19
  • 2
    jQuery is a library – you will almost always incur overhead performance costs for this reason: it's like talking to someone through an interpreter. Unless you want to use raw JavaScript, take advantage of how quick it is to write $('
    ') and accept the performance hit.
    – Danny Bullis Apr 15 '13 at 02:44
  • http://jsperf.com/domcreationtests2 : another interesting jsperf Test. – dgo Apr 21 '13 at 18:20
  • What does "niggling" mean? – hyphen Dec 29 '13 at 02:20
  • 1
    http://jsben.ch/#/bgvCV <= **this benchmark** should answer your question – EscapeNetscape Nov 07 '16 at 12:58
  • does it really matter, if html developers cared this much about efficiency they'd be asking why they couldn't create multiple elements at once instead of asking dom one at a time. There's no winning here. This question is too subjective because you're asking to do something inherently inefficient efficiently(what's more efficient, travelling to school in a jet, or using a catapult?). in all honesty your intent is unique, and there exists a hypothetical parser that will always compile what your intent to document.createElement('div') regardless of the way you do it. – Dmytro Apr 23 '18 at 20:03

12 Answers12

311

I use $(document.createElement('div')); Benchmarking shows this technique is the fastest. I speculate this is because jQuery doesn't have to identify it as an element and create the element itself.

You should really run benchmarks with different Javascript engines and weigh your audience with the results. Make a decision from there.

strager
  • 88,763
  • 26
  • 134
  • 176
  • 17
    jQuery "appends" it to DOM? Where? This doesn't make much sense to me -- where would the div go? – strager Nov 29 '08 at 03:12
  • 29
    a created div in jquery has to be added just like in javascript. $('
    ') by itself isn't attached to the DOM until you append() it to something.
    – Owen Nov 29 '08 at 04:44
  • 2
    @tvanfosson: Sorry buddy, you are wrong again. If you want that `$(document.createElement('div'))` part added to the DOM you will have to append or prepend it to another element (already in the DOM). As it is, the element jquery creates is NOT attached to anything (at least in modern browsers that support documentFragment, AFAIK). – David Murdoch Sep 08 '10 at 13:16
  • 6
    @David - obviously you're right. I will note that I added the comment about 2 years ago just when I was starting to learn jQuery. You would need to do an `appendTo`, ... Because the comments were obviously wrong, I've removed them. – tvanfosson Sep 08 '10 at 13:23
  • 17
    The benchmarking reference is great, but this is also testing the creation of tens of thousands of elements. When will you EVER be dealing with that many elements in a typical situation? Chances are, you've got bigger things to worry about than how to create an element. document.createElement "Ran 39,682 times in 0.097 seconds", whereas $('
    ') "Ran 12,642 in 0.068 seconds." I'd say if something can run thousands of times in less than a second, you're safe.
    – Danny Bullis Apr 15 '13 at 02:11
  • 21
    Furthermore, using $(document.createElement('div')); I would say is less efficient because it takes longer to write for the substantially tiny amount of benefit that you will get in the browser if you are only creating one element at a time here and there. Technically, jQuery itself is less efficient as a library due to look-up costs and for the overhead you incur by using it. If someone is so intent on saving precious thousandths of a milli-second by using document.createElement instead of $('
    '), then they shouldn't be using jQuery :], because $('
    ') is one of the reasons you use it!
    – Danny Bullis Apr 15 '13 at 02:24
  • 3
    Also, the fraction of a millisecond you save is probably lost many times over in the increased download time of the couple of extra bytes the longer code adds. – JJJ Aug 27 '13 at 11:51
  • Another point: If you need the end tag, like `$("
    something
    ")`, some javascript validators will complain about it, because the `` string may break html parsers.
    – zord Dec 01 '13 at 19:29
  • 3
    @fettereddingoskidney Although, the focus of the question _is_ performance, and even if not common there are absolutely cases where you need to create many thousands of element, where the difference in performance noticed here is significant. – Alex Sep 15 '14 at 04:09
  • For example: It can happen for `td` elements as there can be quite many in a large table. – Christophe Roussy Jul 27 '17 at 08:40
  • FYI, I had this same question and created a similar benchmark but for more complex elements with multiple children: https://jsperf.com/jquery-multi-element-creation – Joshua Burns Dec 13 '17 at 01:27
  • I ran the benchmark and the difference was about 5% on Chrome, for others' convenience – Chris May 13 '20 at 23:14
  • 1
    Sorry newbie question: Could you explain where that div will be created on the page? Right now it looks for me as if it's created somewhere on the page so that I wouldn't have control over where the newly created element would appear on the page. – Andreas Aug 13 '20 at 12:54
  • 1
    @Andreas "Could you explain where that div will be created on the page?" $(document.createElement('div')); would create a
    but not put it onto your page. You want to call .appendTo (or a similar method) with where exactly you want to place the new element: https://api.jquery.com/category/manipulation/dom-insertion-inside/
    – strager Aug 14 '20 at 20:41
  • I have a question... Can I trigger click event on this element without appending it to the Dom?? Imagine it is an tag. – AlirezaAsadi Sep 21 '20 at 12:33
166

personally i'd suggest (for readability):

$('<div>');

some numbers on the suggestions so far (safari 3.2.1 / mac os x):

var it = 50000;

var start = new Date().getTime();
for (i = 0; i < it; ++i)  {
  // test creation of an element 
  // see below statements
}
var end = new Date().getTime();
alert( end - start );                

var e = $( document.createElement('div') );  // ~300ms
var e = $('<div>');                          // ~3100ms
var e = $('<div></div>');                    // ~3200ms
var e = $('<div/>');                         // ~3500ms              
Owen
  • 82,995
  • 21
  • 120
  • 115
  • 16
    From the jquery docs: 'When creating single elements use the closing tag or XHTML format. For example, to create a span use $("") or $("") instead of without the closing slash/tag.' – tvanfosson Nov 29 '08 at 02:46
  • 1
    i assumed that was outdated, as the method i describe creates just as valid XHTML. ex: var e = $('
    ').append($('
    ')).html(); alert(e); is there some other metric that would render this method unfavourable to use?
    – Owen Nov 29 '08 at 02:55
  • 7
    @Owen, that behavior is a bug, not a feature. Garbage in, garbage out -- it just so happens that the garbage you get is acceptable. Don't rely on it between jQuery versions, though, unless the specification for the function changes. – strager Nov 29 '08 at 05:15
  • 2
    As expected, seeing similar numbers in Mac OS X Chrome (100ms for createElement() vs. 500ms text parsing) and Mac OS X Firefox (350ms vs. 1000ms). Thanks for writing up the test loop. – Annika Backstrom Feb 05 '10 at 14:15
  • 3
    @tvanfosson This has changed apparently, in the current docs it says: "When the parameter has a single tag (with optional closing tag or quick-closing) — $( "" ) or $( "" ), $( "" ) or $( "" ) — jQuery creates the element using the native JavaScript createElement() function." – metatron Dec 05 '13 at 13:05
  • @metatron I know this is an old question but do you have a link to the docs that say that? Not doubting you, just would like to have the source.. – Marc Stober Feb 22 '15 at 19:33
  • 3
    @MarcStober No offense taken. It's still here: [http://api.jquery.com/jQuery/#jQuery2](http://api.jquery.com/jQuery/#jQuery2). The docs mention _optional closing tag or quick-closing_ – metatron Feb 23 '15 at 09:14
156

Question:

What is the most efficient way to create HTML elements using jQuery?

Answer:

Since it's about jQuery then I think it's better to use this (clean) approach (you are using)

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'text':'Text Only',
}).on('click', function(){
    alert(this.id); // myDiv
}).appendTo('body');

DEMO.

This way, you can even use event handlers for the specific element like

$('<div/>', {
    'id':'myDiv',
    'class':'myClass',
    'style':'cursor:pointer;font-weight:bold;',
    'html':'<span>For HTML</span>',
    'click':function(){ alert(this.id) },
    'mouseenter':function(){ $(this).css('color', 'red'); },
    'mouseleave':function(){ $(this).css('color', 'black'); }
}).appendTo('body');

DEMO.

But when you are dealing with lots of dynamic elements, you should avoid adding event handlers in particular element, instead, you should use a delegated event handler, like

$(document).on('click', '.myClass', function(){
    alert(this.innerHTML);
});

var i=1;
for(;i<=200;i++){
    $('<div/>', {
        'class':'myClass',
        'html':'<span>Element'+i+'</span>'
    }).appendTo('body');
}

DEMO.

So, if you create and append hundreds of elements with same class, i.e. (myClass) then less memory will be consumed for event handling, because only one handler will be there to do the job for all dynamically inserted elements.

Update : Since we can use following approach to create a dynamic element

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    'size': '30'
}).appendTo("body");

But the size attribute can't be set using this approach using jQuery-1.8.0 or later and here is an old bug report, look at this example using jQuery-1.7.2 which shows that size attribute is set to 30 using above example but using same approach we can't set size attribute using jQuery-1.8.3, here is a non-working fiddle. So, to set the size attribute, we can use following approach

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    attr: { size: "30" }
}).appendTo("body");

Or this one

$('<input/>', {
    'type': 'Text',
    'value':'Some Text',
    prop: { size: "30" }
}).appendTo("body");

We can pass attr/prop as a child object but it works in jQuery-1.8.0 and later versions check this example but it won't work in jQuery-1.7.2 or earlier (not tested in all earlier versions).

BTW, taken from jQuery bug report

There are several solutions. The first is to not use it at all, since it doesn't save you any space and this improves the clarity of the code:

They advised to use following approach (works in earlier ones as well, tested in 1.6.4)

$('<input/>')
.attr( { type:'text', size:50, autofocus:1 } )
.val("Some text").appendTo("body");

So, it is better to use this approach, IMO. This update is made after I read/found this answer and in this answer shows that if you use 'Size'(capital S) instead of 'size' then it will just work fine, even in version-2.0.2

$('<input>', {
    'type' : 'text',
    'Size' : '50', // size won't work
    'autofocus' : 'true'
}).appendTo('body');

Also read about prop, because there is a difference, Attributes vs. Properties, it varies through versions.

Community
  • 1
  • 1
The Alpha
  • 143,660
  • 29
  • 287
  • 307
  • What kind of sintax is this $('
    ', {.........}), I've looked for it and I found some similar using $('
    ).attr({......}) ?
    – Rafael Ruiz Tabares May 09 '15 at 17:52
  • @RafaelRuizTabares, in `$('
    ', {...})` you are passing an object which contains all the attributes and in `$('
    ').attr({...})` you are creating an element without any attributes but setting the attributes using `attr()` method later.
    – The Alpha May 09 '15 at 20:39
  • @TheAlpha where can I find info about what I can write inside {}? Because I see they are attributes and events but for
    you use html too. Thanks!
    – Rafael Ruiz Tabares May 11 '15 at 15:34
  • Search `jQuery.com` web site could be helpful @RafaelRuizTabares, or google it :-) – The Alpha May 11 '15 at 18:22
  • 2
    This is by far the cleanest more readable way! Probably not the fast way but certainly less error prone the string addition. Thanks @TheAlpha – Ares Jun 02 '17 at 10:00
37

Actually, if you're doing $('<div>'), jQuery will also use document.createElement().

(Just take a look at line 117).

There is some function-call overhead, but unless performance is critical (you're creating hundreds [thousands] of elements), there isn't much reason to revert to plain DOM.

Just creating elements for a new webpage is probably a case in which you'll best stick to the jQuery way of doing things.

atiquratik
  • 1,296
  • 3
  • 27
  • 34
edwin
  • 2,643
  • 20
  • 17
20

This is not the correct answer for the question but still I would like to share this...

Using just document.createElement('div') and skipping JQuery will improve the performance a lot when you want to make lot of elements on the fly and append to DOM.

Nikos Paraskevopoulos
  • 39,514
  • 12
  • 85
  • 90
Irshad
  • 201
  • 2
  • 2
20

If you have a lot of HTML content (more than just a single div), you might consider building the HTML into the page within a hidden container, then updating it and making it visible when needed. This way, a large portion of your markup can be pre-parsed by the browser and avoid getting bogged down by JavaScript when called. Hope this helps!

Collin Allen
  • 4,449
  • 3
  • 37
  • 52
  • Thanks for the advice. I have used this approach before, however in this particular case I am specifically wanting to know about creating elements. – Darko Nov 29 '08 at 03:27
16

I think you're using the best method, though you could optimize it to:

 $("<div/>");
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
10

You don't need raw performance from an operation you will perform extremely infrequently from the point of view of the CPU.

yfeldblum
  • 65,165
  • 12
  • 129
  • 169
  • Depends on how frequently you are doing it. – Rich Bradshaw Mar 01 '10 at 21:31
  • 8
    The OP is creating a *modal popup*. This operation is not repeated thousands of times per second. Instead, it is repeated maybe once every few seconds, at maximum. Using the `jQuery(html :: String)` method is perfectly fine. Unless the situation is extremely unusual, one will be unlikely to achieve better *perceived* performance. Spend the optimization energy on the cases that could use it. Additionally, jQuery is optimized for speed in many ways. Do sane things with it, and trust-but-verify it to be fast. – yfeldblum Mar 02 '10 at 02:33
9

You'll have to understand that the significance of element creation performance is irrelevant in the context of using jQuery in the first place.

Keep in mind, there's no real purpose of creating an element unless you're actually going to use it.

You may be tempted to performance test something like $(document.createElement('div')) vs. $('<div>') and get great performance gains from using $(document.createElement('div')) but that's just an element that isn't in the DOM yet.

However, in the end of the day, you'll want to use the element anyway so the real test should include f.ex. .appendTo();

Let's see, if you test the following against each other:

var e = $(document.createElement('div')).appendTo('#target');
var e = $('<div>').appendTo('#target');
var e = $('<div></div>').appendTo('#target');
var e = $('<div/>').appendTo('#target');

You will notice the results will vary. Sometimes one way is better performing than the other. And this is only because the amount of background tasks on your computer change over time.

Test yourself here

So, in the end of the day, you do want to pick the smallest and most readable way of creating an element. That way, at least, your script files will be smallest possible. Probably a more significant factor on the performance point than the way of creating an element before you use it in the DOM.

atiquratik
  • 1,296
  • 3
  • 27
  • 34
Jani Hyytiäinen
  • 5,293
  • 36
  • 45
  • I know this is old, but there's no need for jQuery in the first example: `document.getElementById('target).appendChild(document.createElement('div'));` – hisdrewness Mar 08 '17 at 17:18
8

Someone has already made a benchmark: jQuery document.createElement equivalent?

$(document.createElement('div')) is the big winner.

Community
  • 1
  • 1
Erel Segal-Halevi
  • 33,955
  • 36
  • 114
  • 183
7

One point is that it may be easier to do:

$("<div class=foo id=bar style='color:white;bgcolor:blue;font-size:12pt'></div>")

Then to do all of that with jquery calls.

Peter Ajtai
  • 56,972
  • 13
  • 121
  • 140
Tobiah
  • 89
  • 1
  • 1
3

I am using jquery.min v2.0.3 . It's for me better to use following:

var select = jQuery("#selecter");
jQuery("`<option/>`",{value: someValue, text: someText}).appendTo(select);

as following:

var select = jQuery("#selecter");
jQuery(document.createElement('option')).prop({value: someValue, text: someText}).appendTo(select);

Processing time of first code is much lower than second code.

Pascal Venot
  • 215
  • 2
  • 6
Marcel GJS
  • 234
  • 1
  • 10