What is the correct way to write HTML using Javascript?

document.write() doesn't work with XHTML. It's executed after the page has finished loading and does nothing more than write out a string of HTML.

Since the actual in-memory representation of HTML is the DOM, the best way to update a given page is to manipulate the DOM directly.

The way you'd go about doing this would be to programmatically create your nodes and then attach them to an existing place in the DOM. For [purposes of a contrived] example, assuming that I've got a div element maintaining an ID attribute of "header," then I could introduce some dynamic text by doing this:

// create my text
var sHeader = document.createTextNode('Hello world!');

// create an element for the text and append it
var spanHeader = document.createElement('span');
spanHeader.appendChild(sHeader);

// grab a reference to the div header
var divHeader = document.getElementById('header');

// append the new element to the header
divHeader.appendChild(spanHeader);

document.write() will only work while the page is being originally parsed and the DOM is being created. Once the browser gets to the closing </body> tag and the DOM is ready, you can't use document.write() anymore.

I wouldn't say using document.write() is correct or incorrect, it just depends on your situation. In some cases you just need to have document.write() to accomplish the task. Look at how Google analytics gets injected into most websites.

After DOM ready, you have two ways to insert dynamic HTML (assuming we are going to insert new HTML into <div id="node-id"></div>):

  1. Using innerHTML on a node:

    var node = document.getElementById('node-id');
    node.innerHTML('<p>some dynamic html</p>');
    
  2. Using DOM methods:

    var node = document.getElementById('node-id');
    var newNode = document.createElement('p');
    newNode.appendChild(document.createTextNode('some dynamic html'));
    node.appendChild(newNode);
    

Using the DOM API methods might be the purist way to do stuff, but innerHTML has been proven to be much faster and is used under the hood in JavaScript libraries such as jQuery.

Note: The <script> will have to be inside your <body> tag for this to work.