1438
votes

What is the reason browsers do not correctly recognize:

<script src="foobar.js" /> <!-- self-closing script element -->

Only this is recognized:

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

Does this break the concept of XHTML support?

Note: This statement is correct at least for all IE (6-8 beta 2).

9
Works in Chrome and Operacorymathews
Some recent version of Chrome appears to have broken this, self-closing script tags no longer work in ChromeAdam Ness
It isn't just script tags. I don't believe self-closing div tags work either.DOK
As of July 2011, Chrome and Firefox have this problem. "It's not a bug, it's a feature" - really annoying.Martin Konicek
The more general version of this was asked two days later: stackoverflow.com/questions/97522/…Ciro Santilli 新疆再教育营六四事件法轮功郝海东

9 Answers

498
votes

XHTML 1 specification says:

С.3. Element Minimization and Empty Element Content

Given an empty instance of an element whose content model is not EMPTY (for example, an empty title or paragraph) do not use the minimized form (e.g. use <p> </p> and not <p />).

XHTML DTD specifies script elements as:

<!-- script statements, which may include CDATA sections -->
<!ELEMENT script (#PCDATA)>
245
votes

To add to what Brad and squadette have said, the self-closing XML syntax <script /> actually is correct XML, but for it to work in practice, your web server also needs to send your documents as properly formed XML with an XML mimetype like application/xhtml+xml in the HTTP Content-Type header (and not as text/html).

However, sending an XML mimetype will cause your pages not to be parsed by IE7, which only likes text/html.

From w3:

In summary, 'application/xhtml+xml' SHOULD be used for XHTML Family documents, and the use of 'text/html' SHOULD be limited to HTML-compatible XHTML 1.0 documents. 'application/xml' and 'text/xml' MAY also be used, but whenever appropriate, 'application/xhtml+xml' SHOULD be used rather than those generic XML media types.

I puzzled over this a few months ago, and the only workable (compatible with FF3+ and IE7) solution was to use the old <script></script> syntax with text/html (HTML syntax + HTML mimetype).

If your server sends the text/html type in its HTTP headers, even with otherwise properly formed XHTML documents, FF3+ will use its HTML rendering mode which means that <script /> will not work (this is a change, Firefox was previously less strict).

This will happen regardless of any fiddling with http-equiv meta elements, the XML prolog or doctype inside your document -- Firefox branches once it gets the text/html header, that determines whether the HTML or XML parser looks inside the document, and the HTML parser does not understand <script />.

183
votes

Others have answered "how" and quoted spec. Here is the real story of "why no <script/>", after many hours digging into bug reports and mailing lists.


HTML 4

HTML 4 is based on SGML.

SGML has some shorttags, such as <BR//, <B>text</>, <B/text/, or <OL<LI>item</LI</OL>. XML takes the first form, redefines the ending as ">" (SGML is flexible), so that it becomes <BR/>.

However, HTML did not redfine, so <SCRIPT/> should mean <SCRIPT>>.
(Yes, the '>' should be part of content, and the tag is still not closed.)

Obviously, this is incompatible with XHTML and will break many sites (by the time browsers were mature enough to care about this), so nobody implemented shorttags and the specification advises against them.

Effectively, all 'working' self-ended tags are tags with prohibited end tag on technically non-conformant parsers and are in fact invalid. It was W3C which came up with this hack to help transitioning to XHTML by making it HTML-compatible.

And <script>'s end tag is not prohibited.

"Self-ending" tag is a hack in HTML 4 and is meaningless.


HTML 5

HTML5 has five types of tags and only 'void' and 'foreign' tags are allowed to be self-closing.

Because <script> is not void (it may have content) and is not foreign (like MathML or SVG), <script> cannot be self-closed, regardless of how you use it.

But why? Can't they regard it as foreign, make special case, or something?

HTML 5 aims to be backward-compatible with implementations of HTML 4 and XHTML 1. It is not based on SGML or XML; its syntax is mainly concerned with documenting and uniting the implementations. (This is why <br/> <hr/> etc. are valid HTML 5 despite being invalid HTML4.)

Self-closing <script> is one of the tags where implementations used to differ. It used to work in Chrome, Safari, and Opera; to my knowledge it never worked in Internet Explorer or Firefox.

This was discussed when HTML 5 was being drafted and got rejected because it breaks browser compatibility. Webpages that self-close script tag may not render correctly (if at all) in old browsers. There were other proposals, but they can't solve the compatibility problem either.

After the draft was released, WebKit updated the parser to be in conformance.

Self-closing <script> does not happen in HTML 5 because of backward compatibility to HTML 4 and XHTML 1.


XHTML 1 / XHTML 5

When really served as XHTML, <script/> is really closed, as other answers have stated.

Except that the spec says it should have worked when served as HTML:

XHTML Documents ... may be labeled with the Internet Media Type "text/html" [RFC2854], as they are compatible with most HTML browsers.

So, what happened?

People asked Mozilla to let Firefox parse conforming documents as XHTML regardless of the specified content header (known as content sniffing). This would have allowed self-closing scripts, and content sniffing was necessary anyway because web hosters were not mature enough to serve the correct header; IE was good at it.

If the first browser war didn't end with IE 6, XHTML may have been on the list, too. But it did end. And IE 6 has a problem with XHTML. In fact IE did not support the correct MIME type at all, forcing everyone to use text/html for XHTML because IE held major market share for a whole decade.

And also content sniffing can be really bad and people are saying it should be stopped.

Finally, it turns out that the W3C didn't mean XHTML to be sniffable: the document is both, HTML and XHTML, and Content-Type rules. One can say they were standing firm on "just follow our spec" and ignoring what was practical. A mistake that continued into later XHTML versions.

Anyway, this decision settled the matter for Firefox. It was 7 years before Chrome was born; there were no other significant browser. Thus it was decided.

Specifying the doctype alone does not trigger XML parsing because of following specifications.

175
votes

In case anyone's curious, the ultimate reason is that HTML was originally a dialect of SGML, which is XML's weird older brother. In SGML-land, elements can be specified in the DTD as either self-closing (e.g. BR, HR, INPUT), implicitly closeable (e.g. P, LI, TD), or explicitly closeable (e.g. TABLE, DIV, SCRIPT). XML, of course, has no concept of this.

The tag-soup parsers used by modern browsers evolved out of this legacy, although their parsing model isn't pure SGML anymore. And of course, your carefully-crafted XHTML is being treated as badly-written SGML-inspired tag-soup unless you send it with an XML mime type. This is also why...

<p><div>hello</div></p>

...gets interpreted by the browser as:

<p></p><div>hello</div><p></p>

...which is the recipe for a lovely obscure bug that can throw you into fits as you try to code against the DOM.

43
votes

Internet Explorer 8 and earlier do not support XHTML parsing. Even if you use an XML declaration and/or an XHTML doctype, old IE still parse the document as plain HTML. And in plain HTML, the self-closing syntax is not supported. The trailing slash is just ignored, you have to use an explicit closing tag.

Even browsers with support for XHTML parsing, such as IE 9 and later, will still parse the document as HTML unless you serve the document with a XML content type. But in that case old IE will not display the document at all!

28
votes

The people above have already pretty much explained the issue, but one thing that might make things clear is that, though people use <br/> and such all the time in HTML documents, any / in such a position is basically ignored, and only used when trying to make something both parseable as XML and HTML. Try <p/>foo</p>, for example, and you get a regular paragraph.

23
votes

The self closing script tag won't work, because the script tag can contain inline code, and HTML is not smart enough to turn on or off that feature based on the presence of an attribute.

On the other hand, HTML does have an excellent tag for including references to outside resources: the <link> tag, and it can be self-closing. It's already used to include stylesheets, RSS and Atom feeds, canonical URIs, and all sorts of other goodies. Why not JavaScript?

If you want the script tag to be self enclosed you can't do that as I said, but there is an alternative, though not a smart one. You can use the self closing link tag and link to your JavaScript by giving it a type of text/javascript and rel as script, something like below:

<link type="text/javascript" rel ="script" href="/path/tp/javascript" />
21
votes

Unlike XML and XHTML, HTML has no knowledge of the self-closing syntax. Browsers that interpret XHTML as HTML don't know that the / character indicates that the tag should be self-closing; instead they interpret it like an empty attribute and the parser still thinks the tag is 'open'.

Just as <script defer> is treated as <script defer="defer">, <script /> is treated as <script /="/">.

18
votes

Internet Explorer 8 and older don't support the proper MIME type for XHTML, application/xhtml+xml. If you're serving XHTML as text/html, which you have to for these older versions of Internet Explorer to do anything, it will be interpreted as HTML 4.01. You can only use the short syntax with any element that permits the closing tag to be omitted. See the HTML 4.01 Specification.

The XML 'short form' is interpreted as an attribute named /, which (because there is no equals sign) is interpreted as having an implicit value of "/". This is strictly wrong in HTML 4.01 - undeclared attributes are not permitted - but browsers will ignore it.

IE9 and later support XHTML 5 served with application/xhtml+xml.