We all love innerHTML

This article is co-written with Anne van Kesteren, W3C Member and contributor to the WHATWG and Opera specifications, R&D and QA person.

When developing a web page, DOM methods are generally the way to go when dynamically altering elements’ attributes and performing other operations. But what about adding content to a web page in the most efficient manner, both code- and performance wise? We claim that innerHTML is unmatched by any DOM methods available and that it is in most, if not all, situations the best option.

People seem to have this feeling that innerHTML is evil. Instead of one line of innerHTML you would use about twenty lines with calls to the DOM. Every such line making one change. However, innerHTML is actually not that bad. The web browser pretty much parses it much like it parses the original page and builds some DOM nodes out of it which are then inserted at the requested location. Some mutation events are dispatched for the few who care and all is fine.

When it comes to having greater scalability in a web page, especially in AJAX scenarios, innerHTML offers unmatched flexibility. There has also been benchmark tests verifying that innerHTML is more efficient compared to using DOM methods.

The fact that it is not in a standard is simply because nobody got around to it. If you read the mailing list of the W3C Web API’s Working Group you can see that Opera, Mozilla and Apple want it to be standardized and we bet Microsoft would like the same thing. New entrants in the web browser market are probably interested as well given that it has to be supported anyway. That it’s not in a standard is probably its biggest problem, apart from the name which doesn’t really scale well. On the other hand, people complain a lot about document.write() as well which is part of DOM Level 2 HTML.

So, go on! Start, or continue, to use the best tool available for the job!

 

Related reading

41 Comments

  • It’s not innerHTML that is the problem, but constructing HTML with string operations is. (No matter if it is done server side or client side.)

  • Sjoerd,

    Why is it a problem to construct HTML with string operations?

  • Because people tend to forget to escape the DOM</abbr> methods, this isn’t necessary.

    ~Grauw

  • (Well, the comment preview function of this blog clearly isn’t in sync with the server. Let’s try to recreate my comment.)

    Because people tend to forget to escape the < and & characters properly, which will then turn up as bugs, be fixed with ugly regular expressions, and create more bugs.

    With the <abbr>DOM</abbr> methods, this isn’t necessary, as you’re modifying the object model directly instead of a textual representation of it.

    In my experience, it is the cause of a lot of confusion for new <abbr>JS</abbr> programmers. Think ‘it breaks whenever I type a < here’, and ‘If I fix it with a regular expression, the smiley image tags will show up as text’.

    ~Grauw

  • So in essence I’m saying that the problem is not that it’s not standardised (let’s be pragmatic here, all browsers support it), but simply that usually it’s not the right tool for the job :).

    In very early versions of Backbase we were still using innerHTML a lot, and it caused all kinds of bugs like ‘the error messages don’t show for URLs with a & in them’ and quite a couple more. Fortunately, these are long gone now and we learned the hard way that innerHTML is to be avoided for dynamic DOM manipulation as much as possible.

    But feel free to ignore my advise :).

    ~Grauw

  • SÃ&Acir says:

    Talk about error handling : "and builds some DOM nodes out of it which are than inserted at the requested location"

    You have no idea how hard it was for me (not a native English speaker, I'm French) to understand you actually meant "then" not "than".

    Other than that, I have no opinion on the subject (I don't do enough JS). I do wonder though if all UAs really behave in the same way when fed invalid markup with innerHTML. I would assume not, so you then rely on specific error handling. Shouldn't the hypothetical standardized innerHTML clarify that?

  • Lachlan Hunt says:

    I agree with Laurens and Sjoerd that working with strings of markup to manipulate the DOM isn't very good practice. However, innerHTML isn't as bad as document.write() is because of the way document.write() inserts code into the file stream during parsing.

  • I'm going to agree that it should be standardized, because it's just a farce that every browser will have to support it eventually (even with application/xml eventually).

    But, I love beautiful code, and innerHTML is just ugly. I'd much rather write a few more lines of code than write strings of HTML with escaping.

    Dan Webb's DOM Builder is interesting; it saves a few lines of code and makes construction of DOM elements easier but still does it programmatically.

    HTML is HTML, script is script. I don't like combining them if it's not absolutely necessary.

    My mind might change if I ever worked on something huge where DOM methods caused a gigantic performance hit that innerHTML fixed…

  • Tommy Olsson says:

    It’s not innerHTML that is the problem, but constructing HTML with string operations is.

    Hear, hear!

  • Robert Nyman says:

    Thanks for your comments.

    Sjoerd,

    It’s not innerHTML that is the problem, but constructing HTML with string operations is.

    It depends from what point of view you’re looking at it. If it’s from an aesthetic angle, it won’t affect the end result.

    Then, naturally, I don’t propose page after page with concatenating strings, when updating content dynamically it’s often only small parts of code that’s inserted.

    When it comes to AJAX solutions, it’s not about putting HTML string together in the JavaScript but rather to make a call to a certain URL that will return dynamic content transformed into HTML based on the parameters that were sent in.

    Compare that to, for instance, returning XML and doing XSLT transformations on the client, which has much more inconsistent and less support in web browsers.

    Laurens,

    Because people tend to forget to escape the < and & characters properly, which will then turn up as bugs

    Which is the same for unescaped ampersands and > characters directly in the HTML code, so the point is moot. The code has to, naturally, be good code no matter in what layer you write it.

    Sébastien,

    Sorry about that, the typo has been fixed.

    Lachlan,

    Yes, those two are very different things.

    Eric,

    I’m going to agree that it should be standardized, because it’s just a farce that every browser will have to support it eventually (even with application/xml eventually).

    Yes, that’s the whole point. If it’s a de facto standard, it should become a real standard.

  • If it becomes a real standard you can be pretty sure the differences in implementations will be sorted out as well so that it becomes more reliable, even for "AJAX frameworks" and the like.

  • Right, if you generate HTML in a clean way and then use <code>innerHTML</code> to put it somewhere that's perfectly fine of course.

    Which is the same for unescaped ampersands and > characters directly in the HTML code, so the point is moot.

    No it is not. If you type literal HTML, you see the < and & characters right in front of you, and it doesn't look right. But <code>s = "<input value='" + data + "'>";</code> looks fine.

  • Robert Nyman says:

    Sjoerd,

    Maybe I'm missing something here…

    What I meant was that if you write this in the HTML:

    <code><input value="Sjoerd"></code>

    or this in the JavaScript:

    <code>strHTML = "<input value='Sjoerd'>;</code>

    it will generate the same HTML in the DOM. Or did you mean that the variable data in your example might contain invalid/unescaped characters?

  • Being relatively inexperienced with the whole Javascript and DOM deal, I do dislike the idea of constructing HTML using all those DOM methods. Fact remains that <code>innerHTML</code> for people like me is much easier. Another good argument you bring forward is flexibility.

    In essence, there doesn't seem to be a real argument against the use <code>innerHTML</code> except the lack of standardisation. Just because it allows for developers to make errors in the content they would use in conjunction doesn't mean <code>innerHTML</code> itself is flawed — perhaps the developers are?

    Over the next couple of months I'll be exploring this a lot more. Until this article and previously Jonathan Snook's I wasn't even considering <code>innerHTML</code> to be an option. Thanks 🙂

  • When I modified Lea Smart's calendar popup, I changed it to use DOM methods to add the containing div at the top of the body since her original code used document.write to put it in the head element. However for the generated calendar, I used innerHTML because according to PPK's benchmark tests it is faster for large amounts of <acronym title="HyperText Markup Language">HTML</acronym>.

    I agree with Robert:

    The code has to, naturally, be good code no matter in what layer you write it.

    And of course, as I learn more, hopefully my code will get better.

  • Or did you mean that the variable data in your example might contain invalid/unescaped characters?

    Yes, but you can't see it. It doesn't matter how good you can program, somewhere, someday, you'll forget to escape it, I promise! And not only do you need to escape < and & but also the single quote.

  • Robert Nyman says:

    Jeroen, Tanny,

    I'm glad that you agree.

    Sjoerd,

    Yes, absolutely. But then again, that could happen in any layer. One of the customer's web developers might add something invalid in the HTML code, the server-side language might one day suddenly generate something you never expected, or me myself could just plain miss something and produce an error.

    There's never any way to be a 100% sure. I don't think <code>innerHTML</code> is to blame for human behavior in general, though. 🙂

    But, do I think that errors might occurr more often in scenarios like your example, as compared to regular HTML code. Yes, maybe. But to me personally that isn't a reason to refrain from using <code>innerHTML</code>, but rather always be aware of the risks no matter what approach you choose.

  • DOM blows, any way you turn it. It’s clumsy and extremely verbose. Only things like DOM Builder make it tolerable. However, innerHTML blows far worse for exposing you to the vagaries of multiple layers and dealing with escaping.

    So you have a situation where there’s a pragmatic but bug-prone API, and a precise but indescribably painful one.

    The answer is clear: we need cross-browser E4X and we need it now.

  • Robert Nyman says:

    Aristotle,

    So you have a situation where there’s a pragmatic but bug-prone API, and a precise but indescribably painful one.

    I think that sums it up pretty well. But between those two, I'd go for the pragmatic one, given the current situation.

    Not sure if E4X is the solution to all, but it definitely sounds like an interesting option!

  • AsbjÃ&A says:

    Standardising <code>innerHTML</code> is a Good Thing. No doubt. It's a de facto standard and we're all better off with it being a real standard. Let's just hope we can get it better specified, perhaps with some error handling (when the document is in standard mode and invalid markup is inserted, an exception could occur for example) and maybe even a better name (<code>innerMarkup</code> and <code>outerMarkup</code> would be nice).

  • Robert Nyman says:

    Asbjørn,

    I'm happy to hear that you share our opinions!

  • stocknsurf says:

    Hi I am facing a problem with innerhtml in firefox.

    Basically this is the issue:

    I have a divid content which is changed dynamically using innerHTML. This divid is inside a form and as a part of the dynamic content I am adding new form fields dynamically using innerHTML (based on user actions).

    But the problem is when the form is submitted from firefox, these new form fields don't get passed on to the server side at all. Only the static fields that already existed get passed on.

    This is the problem I face only with firefox. On IE the new form fields added using innerHTML gets passed on to the server side successfully.

    I am splitting my hair over this problem with firefox. Has anyone faced the same issue? How do I solve this?

    Thanks

  • Robert Nyman says:

    stocknsurf,

    I haven't encountered this myself, but my guess is that Firefox looks at form fields in a different way. This might be a scenario where you will have to resort to DOM methods like <code>createElement</code>, <code>appendChild</code> etc to make it work.

    Good luck!

  • Tref says:

    stocknsurf, I've just had to debug a similar scenario so in case you haven't located the answer here's what I found out.

    Firefox may not accept your ajax imported form elements if the opening and closing form tags are not nested correctly.

    For example we had a page that had the following structure.

    <code>

    < body>

    < form name="form1" method="post" action="gohere.jsp" >

    < div id="page">

    < div id="main" >

    … main content with form elements went here..

    … some dynamic form elements were inserted using ajax calls

    </div >

    </form >

    </div >

    </body >

    </code>

    We were inserting some form fields into the form via an ajax call but in firefox they were not showing up. We could access them by document.getElementById but document.form1.foo was coming up "undefined"

    The answer was in the nesting of the form fields. The opening tag was between the "page" and "main" divs, whereas the closing tag was after the closing "page" div.

    Hope that helps your situation

    cheers

  • Tref says:

    Forgive me.. my explanation was back to front.. should read

    The answer was in the nesting of the form fields. The opening form tag was above the “page”, whereas the closing tag was between the closing of the "main" and the “page” div.

  • Robert Nyman says:

    Tref,

    Thanks for the info.

  • jp says:

    Thank you so much tref, that was the problem for me too. I thought it would never be solved…

  • zhenya says:

    Tref, I also want to thank you. I've spent 4 hours today trying to solve same problem and after I read your message I only had to make cut-past and it worked!

  • Jiv says:

    In past, I found a way to get rid of the gap IE was putting at the top of the page (equiv. to a ) when inserting the form element like this

    <code>

    </code>

    But if you have a look in the DOM source of Firefox you'll see that weird result

    <code>

    </code>

    This can be a possible cause why your variables doesn't get posted!

  • Cedric Colpaert says:

    I had the same problem with the form elements inside innerhtml.. I've spend hours and hours on this.. and there's only one website (this one) where you can find the solution

  • Robert Nyman says:

    Cedric,

    Glad you found the solution here! 🙂

  • Thanh Le Quoc says:

    Thanks so much…

    I also have faced with this problem.

  • e says:

    In regards to problems with inserting form elements with innerHTML in FireFox, is there some other reading I should find on this site? I ask because it seems that Cedric may have found something more.

    I'm facing a problem very similar to stocknsurf. I'm not quite sure if it's related to nesting of form tags because there aren't any div layers used on this page. Could the way the form is nested inside of tables cause the same problem?

    Everything works fine in FireFox until innerHTML is used to update a select field inside the form. Even when the update doesn't cause any changes to the select field (just re-draws it), FireFox stops recognizing the select field. It's as if the select field no longer exists.

  • e says:

    Also… I'm using a span section around the select field to update it. I'm just giving the span an id and then grabbing onto that with innerHTML.

    All of this works fine in IE, just not FireFox.

    Thanks again.

  • Great article, in firefox, Although, i didn't mess up the tags. But the following may cause the same problem

    <table>

    <form …>

    ….form field mixed with for layout purpose

    </form>

    </table>

    Move to the following format will make the thing work

    <form …>

    <table>

    ….form field mixed with for layout purpose

    </table>

    </form>

    Thanks for reminding although i don't exactly problem as you guys. But it does shorten my debugging time.

    Charlie

  • Darren says:

    Thank you so much all; I had the <form> tags inside the <table> tags . IE had no problems with it, but Firefox, Opera and Safari refused to recognise the AJAX imported select box. 🙂

  • NickW says:

    Tref, Many thanks for this!

  • […] the AJAX imported field and searching the net for a possible solution, I came upon this site (http://www.robertnyman.com/2006/04/20/we-all-love-innerhtml/) where the fix came from one of the readers’ […]

  • sars says:

    from a javascript function , we dynamically pass html to the form using innerhtml

    document.getElementById"provLbl").innerHTML=jsProvLbl;

    document.getElementById("prov").innerHTML=jsProvLbl;

    This values are submitted to the form in IE

    But firefox is not recogising this asa a part of form.CAn anyone help me on this.

    Thank you

  • james crew says:

    thank you for this. my problem solved too.

Leave a Reply to Robert Nyman Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.