Why is document.write considered a "bad practice"?
Asked Answered
P

17

394

I know document.write is considered bad practice; and I'm hoping to compile a list of reasons to submit to a 3rd party vendor as to why they shouldn't use document.write in implementations of their analytics code.

Please include your reason for claiming document.write as a bad practice below.

Psf answered 29/4, 2009 at 15:18 Comment(0)
B
263

A few of the more serious problems:

  • document.write (henceforth DW) does not work in XHTML

  • DW does not directly modify the DOM, preventing further manipulation (trying to find evidence of this, but it's at best situational)

  • DW executed after the page has finished loading will overwrite the page, or write a new page, or not work

  • DW executes where encountered: it cannot inject at a given node point

  • DW is effectively writing serialised text which is not the way the DOM works conceptually, and is an easy way to create bugs (.innerHTML has the same problem)

Far better to use the safe and DOM friendly DOM manipulation methods

Bulk answered 29/4, 2009 at 15:36 Comment(18)
-1, it absolutely modifies the DOM. Everything else is fine. While I understand the urge to depend on structure and methods which can keep you from harm, this may be a case of throwing out the baby with the bathwater.Taphole
(to see that it modifies the DOM, do a document.write in firebug after this page has loaded and then inspect the DOM, and the result (a now cleared page with the contents of your document.write) will be there plain to see.Taphole
Dammit I know this used to be a problem, but I'm struggling to find a browser or situation where it happens. I'll strike it until I've found evidence. Damn my feeble memory.Bulk
FireBug is not a true representation of the DOM. It is mozilla's attempt to parse HTML into a DOM. You can have totally broken HTML look proper in the Firebug DOM view.Psf
Agreed. Trying to address the effects of DW with something like getElementById is the only bulletproof way to tell.Bulk
The DOM is the data structure used to render the page and as such is the alpha and the omega of what the user sees on the page. You are correct that HTML != DOM, but it's immaterial to the question of whether or NOT the DOM is modified by DW. If DW didn't modify the DOM, you don't see the screen - that's true of all browsers and always will be as long as the DOM is what's used to render the page.Taphole
As for Firebug in particular, it's a look into the DOM itself, it doesn't parse HTML, or you would have no view into properties on the DOM which aren't parsed. Even firebug-lite works by inspecting the DOM itself, not parsing the original HTML (even more so)Taphole
@vsync - that is not inserting at a given point that is calling at a given point, do you see the distinction?Bulk
Here is an actual security bug caused by interleaving document.write with appendChild: bugzilla.mozilla.org/show_bug.cgi?id=607222Albuminate
"DW executes where encountered" - not always a disadvantage, indeed it could be considered an advantage for certain things, e.g., adding script elements (actually about the only thing I'd use DW for, and even then I'd think twice).Rowan
"DW executed after the page has finished loading will overwrite the page" This is no longer true, modern browsers do not overwrite the pageBacking
See also Insert in place without document.write.Unload
@RicardoRivaldo Yes, they do, if document.write is called after the document has finished loadingJailhouse
Since XHTML is no longer the latest version of HTML, is it safe to strike through/ignore point #1 now as well? e.g. if you aren't writing in XHTML, why worry about incompatibility with XHTML? Since your JavaScript won't have to interact with anyone else's website, just your own.Goby
The only reason for me is overwriting the page after the document was closed. I really think all the other reasons are silly. Plus if you know how it works, it's not a big deal. Having said that, the only real case is dynamically creating script tags that are synchronous.Novelistic
Chrome 55 will not run document.write if it injects a script and if it meets certain other conditions.Farkas
Problems with DOW, understood. If it were such evil method, it is only fair to deprecate it and eventually remove the support from all browsers (or may be block direct access). How/Why did it manage to live through so many generations of browser evolution and ECMA standard revisions?!! Seems, DOW is not so evil after all, of course, if not misusedHydrargyrum
document.write should not be bad practice. It is bad practice for the scope of most applications, but not all. If you want to call document.open(), and not be able to insert at specific points, it is totally fine!Rennarennane
F
134

There's actually nothing wrong with document.write, per se. The problem is that it's really easy to misuse it. Grossly, even.

In terms of vendors supplying analytics code (like Google Analytics) it's actually the easiest way for them to distribute such snippets

  1. It keeps the scripts small
  2. They don't have to worry about overriding already established onload events or including the necessary abstraction to add onload events safely
  3. It's extremely compatible

As long as you don't try to use it after the document has loaded, document.write is not inherently evil, in my humble opinion.

Francklyn answered 29/4, 2009 at 15:26 Comment(6)
document.write does really horrible things to the html parsers, and is only "extremely compatible" in simple cases.Cauline
Like the insertion of an analytics tag? That is, after all, part of the original question. And by extremely compatible, I mean for just raw browser support for the document.write method.Francklyn
Anything that works with the latest versions of Chrome / IE / Safari / Opera / FireFox is considered compatible.Blaineblainey
Overriding onload events? And what's addEventListener for?Florilegium
Chrome will not run document.write invocations that insert a script when certain conditions are met.Farkas
@Farkas and readers: using document.write to insert a tag for a script from the same domain as the HTML page should be safe.Crosspurpose
A
45

It can block your page

document.write only works while the page is loading; If you call it after the page is done loading, it will overwrite the whole page.

This effectively means you have to call it from an inline script block - And that will prevent the browser from processing parts of the page that follow. Scripts and Images will not be downloaded until the writing block is finished.

Afterpiece answered 14/7, 2011 at 17:19 Comment(0)
I
45

Another legitimate use of document.write comes from the HTML5 Boilerplate index.html example.

<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.3.min.js"><\/script>')</script>

I've also seen the same technique for using the json2.js JSON parse/stringify polyfill (needed by IE7 and below).

<script>window.JSON || document.write('<script src="json2.js"><\/script>')</script>
Ineludible answered 8/9, 2011 at 20:49 Comment(6)
Not bad use here, but still "better" to use DOM manipulation functions -- even Google does it for Google Analytics. Snippet is here.Newmint
@Newmint if you insert a script element via DOM manipulation, is it loaded synchronously? Unless it is, it's not a replacement.Jennifer
@JanDvorak - Good point; when using DOM manipulations, browsers will generally load the script asynchronously. You can use the onload DOM event to determine when the asynchronously loaded script is available for use.Newmint
@JanDvorak It is loaded synchronously if it isn't external (doesn't have src). Otherwise it will be executed "as soon as possible", asynchronously.Intrigant
This still can break, as Chrome will deliberately refuse to run document.write calls that insert <script> tags if the user is on a 2G connection. See developers.google.com/web/updates/2016/08/…Farkas
@Farkas In context, the linked document states that [ injected script tags will not be executed "when all of the following conditions are met". Among the conditions is a requirement that the scrip is not from the same site. So inserting a script from the same site will not be refused.Crosspurpose
C
33

Pro:

  • It's the easiest way to embed inline content from an external (to your host/domain) script.
  • You can overwrite the entire content in a frame/iframe. I used to use this technique a lot for menu/navigation pieces before more modern Ajax techniques were widely available (1998-2002).

Con:

  • It serializes the rendering engine to pause until said external script is loaded, which could take much longer than an internal script.
  • It is usually used in such a way that the script is placed within the content, which is considered bad-form.
Cholecalciferol answered 29/4, 2009 at 16:19 Comment(2)
There are more cons than that. For instance, Google Chrome will refuse to run document.write that creates <script> tag under certain circumstances. developers.google.com/web/updates/2016/08/…Farkas
@Farkas it's worth noting, your comment is over 8 years after my answer and this almost 3 years later. Yeah, there's other cons... and I'd be surprised if document.write itself doesn't go away... as well as possibly some other highly abused interfaces.Cholecalciferol
B
10

Here's my twopence worth, in general you shouldn't use document.write for heavy lifting, but there is one instance where it is definitely useful:

http://www.quirksmode.org/blog/archives/2005/06/three_javascrip_1.html

I discovered this recently trying to create an AJAX slider gallery. I created two nested divs, and applied width/height and overflow: hidden to the outer <div> with JS. This was so that in the event that the browser had JS disabled, the div would float to accommodate the images in the gallery - some nice graceful degradation.

Thing is, as with the article above, this JS hijacking of the CSS didn't kick in until the page had loaded, causing a momentary flash as the div was loaded. So I needed to write a CSS rule, or include a sheet, as the page loaded.

Obviously, this won't work in XHTML, but since XHTML appears to be something of a dead duck (and renders as tag soup in IE) it might be worth re-evaluating your choice of DOCTYPE...

Boorman answered 13/10, 2009 at 13:23 Comment(0)
C
7

It overwrites content on the page which is the most obvious reason but I wouldn't call it "bad".

It just doesn't have much use unless you're creating an entire document using JavaScript in which case you may start with document.write.

Even so, you aren't really leveraging the DOM when you use document.write--you are just dumping a blob of text into the document so I'd say it's bad form.

Closegrained answered 29/4, 2009 at 15:29 Comment(3)
One clarification: document.write inserts contents on the page, it doesn't overwrite them.Sward
@Peter, it does overwrite the content if you call it after the document is loaded. I'm guessing that's what aleemb means.Sidle
Are you suggesting that one should instead manually build the individual DOM nodes in code rather than just doing something like div.innerHTML = "<label for='MySelect'>Choose One</label><select id='MySelect'><option value='foo' selected=''>foo</option><option value='bar'>bar</option></select>";? That seems like it would produce a lot of unnecessary and less readable code. It's also the exact opposite of the approach John Resig and other JS developers advocate.Revels
R
7

Off the top of my head:

  1. document.write needs to be used in the page load or body load. So if you want to use the script in any other time to update your page content document.write is pretty much useless.

  2. Technically document.write will only update HTML pages not XHTML/XML. IE seems to be pretty forgiving of this fact but other browsers will not be.

http://www.w3.org/MarkUp/2004/xhtml-faq#docwrite

Reynoso answered 29/4, 2009 at 15:31 Comment(2)
IE is forgiving because it doesn't support XHTML. If/when they do, document.write will probably stop working (only in XHTML of course).Sidle
XHTML is irrelevant on the web. Even pages with a strict XHTML doctype are not actually treated as XML in that regard, browser developers don't trust page authors that much.Inspector
T
7

It breaks pages using XML rendering (like XHTML pages).

Best: some browser switch back to HTML rendering and everything works fine.

Probable: some browser disable the document.write() function in XML rendering mode.

Worst: some browser will fire an XML error whenever using the document.write() function.

Troika answered 29/4, 2009 at 15:44 Comment(0)
B
5

Chrome may block document.write that inserts a script in certain cases. When this happens, it will display this warning in the console:

A Parser-blocking, cross-origin script, ..., is invoked via document.write. This may be blocked by the browser if the device has poor network connectivity.

References:

Bede answered 1/2, 2017 at 23:3 Comment(0)
D
4

Browser Violation

.write is considered a browser violation as it halts the parser from rendering the page. The parser receives the message that the document is being modified; hence, it gets blocked until JS has completed its process. Only at this time will the parser resume.

Performance

The biggest consequence of employing such a method is lowered performance. The browser will take longer to load page content. The adverse reaction on load time depends on what is being written to the document. You won't see much of a difference if you are adding a <p> tag to the DOM as opposed to passing an array of 50-some references to JavaScript libraries (something which I have seen in working code and resulted in an 11 second delay - of course, this also depends on your hardware).

All in all, it's best to steer clear of this method if you can help it.

For more info see Intervening against document.write()

Dubonnet answered 20/11, 2018 at 1:19 Comment(0)
I
3

Based on analysis done by Google-Chrome Dev Tools' Lighthouse Audit,

For users on slow connections, external scripts dynamically injected via document.write() can delay page load by tens of seconds.

enter image description here

Interview answered 22/2, 2018 at 8:58 Comment(0)
A
3

I don't think using document.write is a bad practice at all. In simple words it is like a high voltage for inexperienced people. If you use it the wrong way, you get cooked. There are many developers who have used this and other dangerous methods at least once, and they never really dig into their failures. Instead, when something goes wrong, they just bail out, and use something safer. Those are the ones who make such statements about what is considered a "Bad Practice".

It's like formatting a hard drive, when you need to delete only a few files and then saying "formatting drive is a bad practice".

Auscultate answered 17/10, 2019 at 23:34 Comment(0)
I
1

One can think of document.write() (and .innerHTML) as evaluating a source code string. This can be very handy for many applications. For example if you get HTML code as a string from some source, it is handy to just "evaluate" it.

In the context of Lisp, DOM manipulation would be like manipulating a list structure, e.g. create the list (orange) by doing:

(cons 'orange '())

And document.write() would be like evaluating a string, e.g. create a list by evaluating a source code string like this:

(eval-string "(cons 'orange '())")

Lisp also has the very useful ability to create code using list manipulation (like using the "DOM style" to create a JS parse tree). This means you can build up a list structure using the "DOM style", rather than the "string style", and then run that code, e.g. like this:

(eval '(cons 'orange '()))

If you implement coding tools, like simple live editors, it is very handy to have the ability to quickly evaluate a string, for example using document.write() or .innerHTML. Lisp is ideal in this sense, but you can do very cool stuff also in JS, and many people are doing that, like http://jsbin.com/

Inflection answered 12/2, 2013 at 17:48 Comment(0)
A
1
  • A simple reason why document.write is a bad practice is that you cannot come up with a scenario where you cannot find a better alternative.
  • Another reason is that you are dealing with strings instead of objects (it is very primitive).
  • It does only append to documents.
  • It has nothing of the beauty of for instance the MVC (Model-View-Controller) pattern.
  • It is a lot more powerful to present dynamic content with ajax+jQuery or angularJS.
Anecdotic answered 9/9, 2016 at 19:37 Comment(2)
As for as your first bullet goes, how are you going to solve what @Boorman describes in his answer above? I agree you could solve it with DOM manipulations, but as DOM manipulations go, it is hard to avoid FUOC at times without document.write.Pothole
Is FUOC a problem anymore?Deepen
I
1

The disadvantages of document.write mainly depends on these 3 factors:

a) Implementation

The document.write() is mostly used to write content to the screen as soon as that content is needed. This means it happens anywhere, either in a JavaScript file or inside a script tag within an HTML file. With the script tag being placed anywhere within such an HTML file, it is a bad idea to have document.write() statements inside script blocks that are intertwined with HTML inside a web page.

b) Rendering

Well designed code in general will take any dynamically generated content, store it in memory, keep manipulating it as it passes through the code before it finally gets spit out to the screen. So to reiterate the last point in the preceding section, rendering content in-place may render faster than other content that may be relied upon, but it may not be available to the other code that in turn requires the content to be rendered for processing. To solve this dilemma we need to get rid of the document.write() and implement it the right way.

c) Impossible Manipulation

Once it's written it's done and over with. We cannot go back to manipulate it without tapping into the DOM.

Impolicy answered 9/12, 2016 at 5:13 Comment(0)
T
-4

I think the biggest problem is that any elements written via document.write are added to the end of the page's elements. That's rarely the desired effect with modern page layouts and AJAX. (you have to keep in mind that the elements in the DOM are temporal, and when the script runs may affect its behavior).

It's much better to set a placeholder element on the page, and then manipulate it's innerHTML.

Timberland answered 29/4, 2009 at 15:31 Comment(6)
This is not true. document.write does not add the content to the end of the page like it's an append. They are written in place.Francklyn
@Peter Bailey, I know this is an old thread, but really this shouldn't be downvoted. whether it appends or not depends on whether document.write() runs inline while the page is loading. If it is called from a function after the page loads then the first document.write() will replace the entire body and subsequent calls will append to it.Hayott
@Hayott Yes, but that's circumstantial. It appends in that scenario only because there's a fresh document. It's still not accurate to say "document.write() appends." Yes, it's an old answer and an old downvote, but I still stand by it.Francklyn
Its fine. I spoke imprecisely. I would've edited it long ago, but there is a much better answer above. I would point out though that "written in place" is equally imprecise.Timberland
document.write replaces the script tag after rendering.Archiepiscopal
DW writes what you need just at the position the script is placed into html code. Not at document end !Pease

© 2022 - 2024 — McMap. All rights reserved.