Thursday, February 17, 2011

Why must we still close SCRIPT elements?

I was wondering why in the world we still have to terminate SCRIPT elements with </script> tags in 2011, fer Pete's sake.

i.e. why does this work:

<script src="foo.js"></script>

but this:

<script src="foo.js" />

does not?

For years I thought it was just a bad implementation from the NS4 days that nobody bothered to correct. Not so! Turns out there's a valid (if a bit irritating) reason.

The tl;dr answer is: <script /> is valid XML, but invalid HTML.

If you serve your HTML pages as text/html, a browser will likely use its HTML parser to render the page. And since <script /> is invalid HTML, the HTML parser treats it as unrecognized junk.

(In theory, if you serve your pages as text/xml or application/xhtml+xml, the browser would use its XML parser, recognize the <script /> as valid, and load/execute the associated JS. But that also presumes your documents are also perfectly-formed, valid XML and not tag soup. Can you make that claim?)

As to the question of why <script /> is invalid while <img /> is perfectly okay:

The XHTML spec (and therefore HTML5, which imports the element definitions from the XHTML DTD) defines the SCRIPT tag as containing "document text." It cannot, by definition, be "empty."

SCRIPT is often considered analogous to the IMG element -- and mistakenly so -- because they both use the "src" attribute. In reality, SCRIPT is more akin to the P (paragraph) element, which also cannot be empty (writing <p /> is invalid -- you must instead write <p></p>)

For comparison, here are the starting element definitions from the XHTML DTD:

<!ELEMENT script (#PCDATA)>

<!ELEMENT img EMPTY>

This is why <img /> is fine, while <script /> is a no-no.

6 Comments:

At 3:31 PM, Blogger Andrex said...

I think it's more analogous to the link element, but that's more because I group them together. Even still, who writes anything within a script tag anymore? The spec should be changed so that you can leave off the closing tag (and also the closing slash in HTML mode), but that might mess with old browsers I guess.

 
At 6:19 AM, Blogger Michael(tm) Smith said...

It's more closely analogous to the style element. And the reason you wouldn't expect to be able to omit the end tag for the style element is the same reason for not expecting to be able to do it for the script element.

 
At 12:44 AM, Blogger Da Scritch said...

The other problem with serving xml pages is the document.write disapearing.
Even if you write well done JS code, if you use ANY WYSIWYG editor like Fck, TinyMCE,... , you will got a soup of document.write()...

 
At 3:56 PM, Blogger scottandrew said...

It's more closely analogous to the style element.

True! But I think that's unintuitive because external styles are usually fetched with a LINK element unlike SCRIPT, which serves both purposes.

 
At 12:34 PM, Blogger Alistair said...

There's quite a lot in this that's just plain wrong, sorry. (I've had to substitute square brackets here.)

You say "[script /] is invalid HTML, the HTML parser treats it as unrecognized junk." That's not right. The script tag is correctly parsed as an opening tag. And what's inside? The rest of your html. That's why it stuffs everything up.

Then you write: "writing [p /] is invalid -- you must instead write [p][/p]" - no, usually [p] doesn't require a closing tag. Same as [html], [body], [li] etc.

The key here is that some parsers don't recognise the xml syntax for empty elements. [script] has to be closed because, if you're not specifying an external source, there's an implicit content. [img] doesn't need to be closed because there's no content. [img /] is fine - the parser just ignores the trailing slash.

 
At 2:56 AM, Blogger salesroles said...

The other problem with serving xml pages is the document.write disapearing.
Even if you write well done JS code, if you use ANY WYSIWYG editor like Fck, TinyMCE,... , you will got a soup of document.write()...

Yeah I have found that out especially Fck
any answers...?

 

Post a Comment

<< Home