Почему не работают самозакрывающиеся элементы скрипта?


1346

По какой причине браузеры неправильно распознают:

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

Только это признается:

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

Это нарушает концепцию поддержки XHTML?

Примечание: это утверждение верно по крайней мере для всех IE (6-8 бета 2).


12
Работает в Chrome и Opera
corymathews

46
Некоторые недавние версии Chrome, похоже, нарушили самозакрывающиеся теги сценариев, которые больше не работают в Chrome
Адам Несс

13
Это не просто теги сценария. Я не верю, что самозакрывающиеся теги div тоже работают.
DOK

6
По состоянию на июль 2011 года, Chrome и Firefox имеют эту проблему. «Это не ошибка, это особенность» - действительно раздражает.
Мартин Коничек

4
Более общую версию этого спросили два дня спустя: stackoverflow.com/questions/97522/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Ответы:


481

Спецификация XHTML 1 гласит:

С.3. Минимизация элементов и содержание пустых элементов

Для данного пустого экземпляра элемента, модель содержимого которого не является EMPTY(например, пустой заголовок или абзац), не используйте свернутую форму (например, используйте <p> </p>и не используйте <p />).

DTD XHTML определяет элементы сценария как:

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

111
Тем не менее, «не надо» не то же самое, что «не должен» Это руководство (для совместимости, как предлагается в заголовке раздела), а не правило.
Конрад Рудольф

42
На самом деле, я не могу найти какое-либо применение для этого ограничения :) Это кажется полностью искусственным.
эскадрилья

22
Правильный ответ дал olavk. Приложение C XHTML 1.0 - это не причина, по которой вещи такие, какие они есть, а просто то, как все обходится.
hsivonen

32
Это не нормативная часть спецификации. Это только приложение о том, как работать с браузерами, которые не поддерживают XHTML
Корнел

12
Проблема <script />не в том, что спецификация запрещает его, а в том, что браузеры не интерпретируют его как «non-tag-soup», если тип контента не application / xhtml + xml. См .: stackoverflow.com/questions/348736/… @shabunc: могут показаться , что браузеры это понимают, но на самом деле происходит размещение содержимого после <p /> внутри абзаца, поскольку интерпретация цитаты squadette означает, что с < p> не пустой, он не может быть самозакрывающимся. В XHTML 1.1 он может быть самозакрывающимся.
Джо

241

Чтобы добавить к тому, что сказали Брэд и Сквадетт, самозакрывающийся синтаксис XML на <script />самом деле является правильным XML, но для того, чтобы он работал на практике, вашему веб-серверу также необходимо отправить ваши документы в виде правильно сформированного XML с миметипом XML, как application/xhtml+xmlв HTTP Заголовок Content-Type (а не как text/html).

Однако, отправка mimetype XML приведет к тому, что IE7 не будет анализировать ваши страницы, что только нравится text/html.

С w3 :

Таким образом, «application / xhtml + xml» ДОЛЖЕН использоваться для документов семейства XHTML, а использование «text / html» ДОЛЖНО быть ограничено HTML-совместимыми документами XHTML 1.0. «application / xml» и «text / xml» МОГУТ также использоваться, но при необходимости «application / xhtml + xml» ДОЛЖНЫ использоваться, а не эти общие типы носителей XML.

Я ломал голову над этим несколько месяцев назад, и единственным работоспособным (совместимым с FF3 + и IE7) решением было использование старого <script></script>синтаксиса с text/html(HTML syntax + HTML mimetype).

Если ваш сервер отправляет text/htmlтип в своих заголовках HTTP, даже если документы XHTML правильно сформированы иным образом, FF3 + будет использовать режим отображения HTML, что означает, что <script />он не будет работать (это изменение, ранее Firefox был менее строгим).

Это будет происходить независимо от того, какие возни с http-equivметаэлементами, прологом XML или документом внутри вашего документа - Firefox разветвляется после того, как получает text/htmlзаголовок, который определяет, будет ли парсер HTML или XML заглядывать внутрь документа, а парсер HTML не понимает <script />.


3
Правильно ли тогда сделать вывод, что если вы откажетесь от поддержки IE7, отправка text / xml обеспечит вам широкую поддержку браузера <script />?
Крис Москини

7
Короче говоря, <script /> будет работать, только если ваш MIME-тип страницы - xhtml / xml. Для обычных текстовых / html-страниц это не сработает. И если мы попытаемся использовать MIME-тип "xhtml / xml", это нарушит совместимость IE. Подводя итог, сохраняйте спокойствие и используйте <script> ... </ script> Спасибо, Джо ;-)
Navin Israni

1
Отличное объяснение. Еще один момент, на который стоит обратить внимание, заключается в том, что Firefox также будет .htmlотображать локальные файлы в виде тега-супа независимо от мета-тегов по аналогичным причинам. Для файлов XHTML Firefox будет отображать их соответствующим образом, только если они названы .xhtml.
alecov

@ChrisMoschini. Возможно, но использовать application/xhtml+xml, а не text/xml.
TRIG

167

В случае, если кому-то интересно, окончательная причина в том, что HTML изначально был диалектом SGML, который является странным старшим братом XML. В земле SGML элементы могут быть определены в DTD как самозакрывающиеся (например, BR, HR, INPUT), неявно закрываемые (например, P, LI, TD) или явно закрываемые (например, TABLE, DIV, SCRIPT). XML, конечно, не имеет понятия об этом.

Парсеры тег-супа, используемые современными браузерами, развились из этого наследия, хотя их модель синтаксического анализа больше не является чистым SGML. И, конечно же, ваш тщательно созданный XHTML рассматривается как плохо написанный SGML-вдохновленный тег-суп, если вы не отправите его с типом mime XML. Это также почему ...

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

... интерпретируется браузером как:

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

... что является рецептом для милой непонятной ошибки, которая может привести вас в ярость, когда вы пытаетесь кодировать против DOM.


4
Мне любопытно. почему браузер предпочитает интерпретировать это так?
Ахмед Эон Аксан

32
@AhmedAeonAxan: Pэлемент не может содержать DIVэлементы (это недопустимый HTML), поэтому браузер неявно закрывает Pэлемент (определенный как «неявно закрываемый ») перед открывающим DIVтегом. Однако браузеры, как правило, ведут себя по-разному в этом отношении (как они могут поступать с любым недопустимым HTML).
MrWhite

5
@ColeJohnson Нет, это не суп с тегами; greim запутывает границу между действительным и недействительным HTML. Тег суп - это то, что вы получаете, когда авторам нет дела до правил, потому что браузеры используют исправление ошибок. С </p>другой стороны, отсутствующий конечный тег фактически является частью определения HTML!
Мистер Листер

3
@MrLister - вроде. «Теговый суп» описывает, как анализируется HTML, а не как он создается. Этот термин использовался для описания разрозненных стратегий, используемых браузерами для понимания HTML, и отличается от строгого синтаксического анализа XML. Синтаксический анализ XML разрешен только для типов mime-файлов XML, но поскольку они так и не получили широкого распространения, браузеры прибегли к различным схемам «тегового супа», даже для других действительных документов.
Грейм

8
HTML5 фактически стандартизировал разбор «супа тега», включая последовательный способ обработки неверной разметки. До этого браузерам приходилось самостоятельно выяснять, что делать с неверной разметкой, вызывая несоответствия. Анализатор HTML в современных браузерах является одним из самых продвинутых программ, когда-либо написанных. Поразительно быстро и может справиться с большинством любых входных данных, обеспечивая стабильные результаты.
Стейн де Витт

161

Другие ответили «как» и процитировали спец. Вот реальная история «почему нет <script/>», после многих часов копания в отчетах об ошибках и списках рассылки.


HTML 4

HTML 4 основан на SGML .

SGML имеет некоторый shorttags , такие как <BR//, <B>text</>, <B/text/или <OL<LI>item</LI</OL>. XML принимает первую форму, переопределяет окончание как «>» (SGML гибкий), так что он становится <BR/>.

Тем не менее, HTML не доработал, так что <SCRIPT/> должно означать <SCRIPT>> .
(Да, символ «>» должен быть частью содержимого, а тег все еще не закрыт.)

Очевидно, что это несовместимо с XHTML и приведет к поломке многих сайтов (к тому времени, когда браузеры были достаточно зрелыми, чтобы позаботиться об этом ), поэтому никто не реализовал ярлыки и спецификация не советует против них .

По сути, все «рабочие» самозавершающиеся теги являются тегами с запрещенным конечным тегом в технически несовместимых синтаксических анализаторах и фактически являются недействительными. Это был W3C, который придумал этот хак, чтобы помочь перейти на XHTML, сделав его HTML-совместимым .

И <script>конец тега не запрещен .

«Самозавершающийся» тег - это взлом в HTML 4 и бессмысленный.


HTML 5

HTML5 имеет пять типов тегов, и только «пустые» и «внешние» теги могут быть самозакрывающимися .

Поскольку <script>не является пустым (оно может иметь содержимое) и не является чужим (например, MathML или SVG), <script>его нельзя закрывать самостоятельно, независимо от того, как вы его используете.

Но почему? Разве они не могут расценить это как чужое, сделать особый случай или что-то?

HTML 5 стремится быть обратно совместимым с реализациями HTML 4 и XHTML 1. Он не основан на SGML или XML; его синтаксис в основном связан с документированием и объединением реализаций. (Вот почему <br/> <hr/>и т. Д. Допустимы HTML 5, хотя и являются недействительными HTML4.)

Самозакрытие - <script>это один из тегов, в которых реализации различаются. Он используется для работы в Chrome, Safari , и Opera ; насколько мне известно, он никогда не работал в Internet Explorer или Firefox.

Это обсуждалось, когда HTML 5 разрабатывался и был отклонен, потому что он нарушает совместимость браузера . Веб-страницы, которые автоматически закрывают тег сценария, могут отображаться некорректно (если вообще) в старых браузерах. Были и другие предложения , но они также не могут решить проблему совместимости.

После того, как черновик был выпущен, WebKit обновил синтаксический анализатор до соответствия.

Самозакрытие <script>не происходит в HTML 5 из-за обратной совместимости с HTML 4 и XHTML 1.


XHTML 1 / XHTML 5

Когда действительно служил XHTML, <script/>он действительно закрыт, как утверждают другие ответы .

За исключением того, что спецификация говорит, что это должно работать, когда используется как HTML:

Документы XHTML ... могут быть помечены интернет-медиа-типом "text / html" [RFC2854], так как они совместимы с большинством браузеров HTML.

Так что случилось?

Люди попросили Mozilla , чтобы позволить Firefox разобрать , соответствующие документы в XHTML , независимо от указанного содержания заголовка (известного как фырканье контента ). Это позволило бы самозакрывающимся сценариям, и в любом случае необходим анализ содержимого, поскольку веб-хостеры не были достаточно зрелыми, чтобы обслуживать правильный заголовок; IE был хорош в этом .

Если первая война браузеров не закончилась с IE 6, возможно, XHTML также был в списке. Но это закончилось. И IE 6 имеет проблемы с XHTML. На самом деле IE не поддерживает правильный тип MIME вообще , заставляя всех использовать text/htmlдля XHTML , потому что IE провел значительную долю рынка в течение целого десятилетия.

А также прослушивание контента может быть очень плохим, и люди говорят, что его следует остановить .

Наконец, оказывается, что W3C не подразумевал, что XHTML может быть сниффином : документ - это и HTML, и XHTML, и Content-Typeправила. Можно сказать, что они твердо стояли на «просто следуйте нашим спецификациям» и игнорировали то, что было практичным . Ошибка, которая продолжалась в более поздних версиях XHTML.

Так или иначе, это решение решило вопрос для Firefox. Прошло 7 лет, прежде чем Chrome родился ; не было другого значимого браузера. Так было решено.

Только указание типа документа не вызывает синтаксический анализ XML из-за следующих спецификаций.


1
@AndyE Когда вы пишете самозакрывающийся <script>, основные браузеры в то время не думают, что он закрыт, и будут анализировать html подпоследовательности как javascript, что приведет к разрыву действительного HTML5 в этих старых браузерах. Таким образом, предложение отклонено. Это объясняется в связанном списке рассылки HTML5.
Sheepy

2
@AndyE: Вы описываете прямую совместимость - способность старого кода работать с новым компилятором / интерпретатором / анализатором. Обратная совместимость - это способность нового кода работать со старым компилятором / интерпретатором / парсером. Так что да, проблема заключалась в обратной совместимости, так как в противном случае страницы, написанные с учетом новой спецификации, не работали бы в старых браузерах (и да, это традиция веб-программирования - стараться, чтобы новый код работал в старых браузерах как можно больше).
Slebetman

3
@Dmitry Реальность такова, что запрет самозакрытого сценария - улица с односторонним движением. Как связанно , сам-замкнутыми <скрипт> сломает все браузеры, пользователи будут просто увидеть пустую страницу - игровые приставки, интернет - телевидение, в IE 11 на новом корпоративном Win7 ПК, миллионы Java времени выполнения , или миллиарды смартфонов. Можете ли вы обновить большинство WebView большинства языков на большинстве устройств? Если бы HTML5 попытался это сделать, они бы потерпели неудачу, как XHTML2.
Sheepy

6
очень недооцененный ответ
Камил Томшик

2
Немного исправления: теги, которые в HTML работают как самозакрывающиеся, - это не теги с необязательными конечными тегами, а теги с запрещенными конечными тегами (пустые или недействительные теги). Теги с необязательными конечными тегами, такими как <p>или <li>, не могут быть «самозакрытыми», так как они могут иметь контент, поэтому код подобен <p/>не более, чем (неправильно сформированный) начальный тег и содержимое после него, если это разрешено в этом элементе , в конечном итоге внутри него.
Илья Стрельцын

44

Internet Explorer 8 и более ранние версии не поддерживают синтаксический анализ XHTML. Даже если вы используете декларацию XML и / или тип документа XHTML, старый IE все равно анализирует документ как обычный HTML. А в простом HTML самозакрывающийся синтаксис не поддерживается. Конечная косая черта просто игнорируется, вы должны использовать явный закрывающий тег.

Даже браузеры с поддержкой синтаксического анализа XHTML, такие как IE 9 и более поздние версии, все равно будут анализировать документ как HTML, если вы не предоставите документ с типом содержимого XML. Но в этом случае старый IE не будет отображать документ вообще!


9
«IE не поддерживает синтаксический анализ XHTML». было верно для версий IE в то время, когда это было написано, но больше не верно.
EricLaw

@EricLaw, вы можете уточнить, какая версия IE исправила это? (и любые конкретные условия - например, требуется действительный тип документа)
scunliffe

2
@scunliffe IE9 была первой версией с полной поддержкой XHTML. blogs.msdn.com/b/ie/archive/2010/11/01/…
EricLaw

28

Вышеупомянутые люди уже в значительной степени объяснили эту проблему, но одна вещь, которая может прояснить ситуацию, заключается в том, что, хотя люди используют <br/>и такое все время в HTML-документах, любое /в таком положении в основном игнорируется и используется только при попытке сделать что-то и разбирается как XML и HTML. Попробуйте <p/>foo</p>, например, и вы получите обычный абзац.


22

Самозакрывающийся тег сценария не будет работать, поскольку тег сценария может содержать встроенный код, а HTML недостаточно умен, чтобы включать или отключать эту функцию в зависимости от наличия атрибута.

С другой стороны, HTML имеет отличный тег для включения ссылок на внешние ресурсы: <link>тег, и он может быть самозакрывающимся. Он уже используется для включения таблиц стилей, каналов RSS и Atom, канонических URI и всех других вкусностей. Почему не JavaScript?

Если вы хотите, чтобы тег script был самодостаточным, вы не можете сделать это, как я уже сказал, но есть альтернатива, хотя и не разумная. Вы можете использовать самозакрывающийся тег link и ссылку на свой JavaScript, задав ему тип text / javascript и rel as script, что-то вроде ниже:

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

4
Мне нравится это, почему это не "умный", хотя?
Джош М.

5
Потому что есть предопределенный тег сценария, который точно выполняет работу по загрузке сценария. Почему вы путаете вопросы, используя что-то еще? Молотком забивает гвозди. Было бы разумно использовать обувь?
Дейв Лоуренс,

8
@daveL - у нас есть <style>теги, но мы используем теги ссылок для внешних CSS-файлов. Определение тега ссылки: « Тег <link> определяет ссылку между документом и внешним ресурсом». Кажется совершенно логичным, что тег link будет использоваться для внешних CSS или JS ... это то, для чего он ... ссылки во внешних файлах. обратите внимание, я не говорю о спецификации / кросс-браузерности / и т.д., я просто комментирую логическую природу использования тегов ссылок для ввода как CSS, так и JS ... на самом деле было бы много смысла, если бы это было так , Не уверен, что обувь [аналогия] подходит.
Джимбо Джонни

20

В отличие от XML и XHTML, HTML не знает самозакрывающегося синтаксиса. Браузеры, которые интерпретируют XHTML как HTML, не знают, что /символ указывает, что тег должен быть самозакрывающимся; вместо этого они интерпретируют его как пустой атрибут, и синтаксический анализатор все еще думает, что тег «открыт».

Так же, как <script defer>лечится, так <script defer="defer">и <script />лечится, как <script /="/">.


33
Это элегантное объяснение на самом деле неверно. Если бы это было так, то для элемента script в DOM был бы атрибут "/". Я проверил IE, Firefox и Opera, и ни один из них не содержит такого атрибута.
Alohci

11
/ не является допустимым символом имени атрибута, поэтому он отбрасывается. В противном случае это объяснение довольно ясно.
Hallvors - восстановить Монику

1
На самом деле, некоторые HTML-парсеры (и особенно валидаторы) могут интерпретировать /как часть конструкции NET (Null End Tag).
IllidanS4 хочет вернуть Монику

18

Internet Explorer 8 и старше не поддерживает правильный тип MIME для XHTML application/xhtml+xml. Если вы используете XHTML как text/html, что необходимо для этих более старых версий Internet Explorer, это будет интерпретироваться как HTML 4.01. Вы можете использовать только короткий синтаксис с любым элементом, который разрешает пропуск закрывающего тега. См. Спецификацию HTML 4.01 .

«Краткая форма» XML интерпретируется как атрибут с именем /, который (из-за отсутствия знака равенства) интерпретируется как имеющий неявное значение «/». Это абсолютно неправильно в HTML 4.01 - необъявленные атрибуты запрещены, но браузеры игнорируют это.

IE9 , а затем поддержка XHTML 5 служил application/xhtml+xml.


IE 9 поддерживает XHTML, и IE больше не> 51%. Не могли бы вы обновить свой ответ?
Дамиан Йеррик

5

Это потому, что TAG СКРИПТА не является пустым элементом.

В HTML-документе - VOID ELEMENTS вообще не нужен закрывающий тег!

В xhtml все является универсальным, поэтому все они требуют завершения, например, «закрывающий тег»; В том числе br, простой перенос строки, как <br></br>или его стенография <br /> .

Однако элемент Script никогда не является пустым или параметрическим элементом, потому что тег script, прежде всего, является инструкцией браузера, а не объявлением описания данных.

В принципе, инструкция семантического завершения, например, «закрывающий тег», требуется только для обработки инструкций, семантика которых не может быть завершена последующим тегом. Например:

<H1>семантика не может быть прервана следующим, <P>потому что она не несет достаточно своей собственной семантики, чтобы переопределить и, следовательно, завершить предыдущий набор команд H1. Несмотря на то, что он сможет разбить поток на новую строку абзаца, он недостаточно «силен», чтобы переопределить текущий размер шрифта и высоту стиля строки, стекающую по потоку , то есть вытекающую из H1 (потому что у P его нет ).

Вот как и почему была изобретена сигнализация "/" (завершение).

Общий тег завершения без описания, подобный < />, был бы достаточен для любого отдельного падения встречного каскада, например: <H1>Title< />но это не всегда так, потому что мы также хотим иметь возможность «вложения», множественных промежуточных тегов потока: split в торренты, прежде чем обматывать / падать на другой каскад. Как следствие, общий терминатор, такой как < />, не сможет определить цель свойства для завершения. Например: <b>полужирный <i>полужирный < /> курсив </> нормальный. Несомненно, не сможет правильно понять наше намерение и, скорее всего, будет истолковывать его как полужирный полужирный шрифт полужирный нормальный.

Так родилось понятие обертки, т. Е. Контейнера. (Эти понятия настолько похожи, что их невозможно различить, и иногда один и тот же элемент может иметь и то и другое. <H1>Является и оболочкой, и контейнером одновременно. Тогда как <B>только семантическая оболочка). Нам понадобится простой контейнер без семантики. И, конечно, изобретение элемента DIV пришло.

Элемент DIV на самом деле является 2BR-контейнером. Конечно, появление CSS сделало всю ситуацию более странной, чем могло бы быть, и вызвало большую путаницу со многими великими последствиями - косвенно!

Поскольку с помощью CSS вы можете легко переопределить нативное поведение до и после BR недавно изобретенного DIV, его часто называют «контейнером бездействия». Что, естественно, неправильно! DIVs являются блочными элементами и будут изначально прерывать линию потока как до, так и после сигнализации окончания. Вскоре в сети начали страдать страницы DIV-itis. Большинство из них до сих пор.

Появление CSS с его способностью полностью переопределить и полностью переопределить нативное поведение любого HTML-тега, каким-то образом сумело запутать и затуманить весь смысл существования HTML ...

Внезапно все HTML-теги выглядели как устаревшие, они были испорчены, лишены всего их первоначального значения, идентичности и цели. Каким-то образом у вас сложится впечатление, что они больше не нужны. Говоря: одного тега контейнера-обертки будет достаточно для всего представления данных. Просто добавьте необходимые атрибуты. Почему бы не иметь значимые теги вместо этого; Придумайте имена тегов по мере необходимости и позвольте CSS возиться с остальными.

Вот как родился xhtml и, конечно, великий тупой, столь дорого заплативший новичкам и искаженное видение того, что к чему, и какова чертова цель всего этого. W3C перешел из World Wide Web в "Что пошло не так, товарищи?"

Цель HTML - передавать значимые данные человеку-получателю.

Для доставки информации.

Формальная часть предназначена только для обеспечения ясности доставки информации. xhtml не дает ни малейшего рассмотрения информации. - Для него информация абсолютно неактуальна.

Самое важное в этом вопросе - это знать и понимать, что xhtml - это не просто версия какого-то расширенного HTML , xhtml - это совершенно другой зверь; обосновывается; и поэтому разумно держать их отдельно.


3

Разница между 'true XHTML', 'faux XHTML' и HTML, а также важность типа MIME, отправляемого сервером, уже хорошо описана здесь . Если вы хотите попробовать это прямо сейчас, вот простой редактируемый фрагмент с предварительным просмотром в реальном времени, включая самозакрывающийся тег сценария для браузеров с поддержкой:

div { display: flex; }
div + div {flex-direction: column; }
<div>Mime type: <label><input type="radio" onchange="t.onkeyup()" id="x" checked  name="mime"> application/xhtml+xml</label>
<label><input type="radio" onchange="t.onkeyup()" name="mime"> text/html</label></div>
<div><textarea id="t" rows="4" 
onkeyup="i.src='data:'+(x.checked?'application/xhtml+xml':'text/html')+','+encodeURIComponent(t.value)"
><?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
[<!ENTITY x "true XHTML">]>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
  <p>
    <span id="greet" swapto="Hello">Hell, NO :(</span> &x;.
    <script src="data:text/javascript,(g=document.getElementById('greet')).innerText=g.getAttribute('swapto')" />
    Nice to meet you!
    <!-- 
      Previous text node and all further content falls into SCRIPT element content in text/html mode, so is not rendered. Because no end script tag is found, no script runs in text/html
    -->
  </p>
</body>
</html></textarea>

<iframe id="i" height="80"></iframe>

<script>t.onkeyup()</script>
</div>

Вы должны увидеть Hello, true XHTML. Nice to meet you!ниже текстовую область.

Для неспособных браузеров вы можете скопировать содержимое текстовой области и сохранить его в виде файла с .xhtml(или .xht) расширением ( спасибо Алеку за эту подсказку ).


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.