Почему не работают самозакрывающиеся теги скрипта?
По какой причине браузеры неправильно распознают:
<script src="foobar.js" /> <!-- self-closing script tag -->
Только это признается:
<script src="foobar.js"></script>
Это нарушает концепцию поддержки XHTML?
Примечание: это утверждение верно по крайней мере для всех IE (6-8 бета 2).
11 ответов
Спецификация XHTML 1 гласит:
С.3. Минимизация элементов и содержание пустых элементов
Дан пустой экземпляр элемента, модель содержимого которого не
EMPTY
(например, пустой заголовок или абзац) не используйте свернутую форму (например, используйте<p> </p>
и не<p />
).
DTD XHTML определяет теги сценария как:
<!-- script statements, which may include CDATA sections -->
<!ELEMENT script (#PCDATA)>
Чтобы добавить к тому, что сказали Брэд и Сквадетт, самозакрывающийся синтаксис XML <script />
на самом деле это правильный XML, но для того, чтобы он работал на практике, ваш веб-сервер также должен отправлять ваши документы в виде правильно сформированного XML с типом mime-типа 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 + Mimetype HTML).
Если ваш сервер отправляет text/html
введите HTTP-заголовки, даже если XHTML-документы правильно сформированы, FF3+ будет использовать режим рендеринга HTML, что означает, что <script />
работать не будет (это изменение, ранее Firefox был менее строгим).
Это произойдет независимо от того, http-equiv
метатеги, пролог XML или doctype внутри вашего документа - Firefox разветвляется, как только он получает text/html
заголовок, который определяет, будет ли анализатор HTML или XML выглядеть внутри документа, а анализатор HTML не понимает <script />
,
Другие ответили "как" и процитировали спец. Вот настоящая история "почему нет <script/>
", после многих часов копания в отчетах об ошибках и списках рассылки.
HTML 4
HTML 4 основан на SGML.
SGML имеет несколько ярлыков, таких как <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 из-за следующих спецификаций.
В случае, если кому-то интересно, окончательная причина в том, что 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.
Internet Explorer 8 и более ранние версии не поддерживают синтаксический анализ XHTML. Даже если вы используете декларацию XML и / или тип документа XHTML, старый IE все равно анализирует документ как обычный HTML. А в простом HTML самозакрывающийся синтаксис не поддерживается. Конечная косая черта просто игнорируется, вы должны использовать явный закрывающий тег.
Даже браузеры с поддержкой синтаксического анализа XHTML, такие как IE 9 и более поздние версии, все равно будут анализировать документ как HTML, если вы не предоставите документ с типом содержимого XML. Но в этом случае старый IE не будет отображать документ вообще!
Люди выше уже в значительной степени объяснили проблему, но одна вещь, которая может прояснить ситуацию, заключается в том, что, хотя люди используют '<br/>'
и такое все время в HTML
документы, любые '/'
в такой позиции в основном игнорируется, и используется только при попытке сделать что-то как разбирается как XML
а также HTML
, Пытаться '<p/>foo</p>'
Например, и вы получите обычный абзац.
Самозакрывающийся тег сценария не будет работать, поскольку тег сценария может содержать встроенный код, а 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" />
В отличие от XML и XHTML, HTML не знает самозакрывающегося синтаксиса. Браузеры, которые интерпретируют XHTML как HTML, не знают, что /
символ указывает, что тег должен быть самозакрывающимся; вместо этого они интерпретируют его как пустой атрибут, и анализатор все еще думает, что тег "открыт".
Как только <script defer>
рассматривается как <script defer="defer">
, <script />
рассматривается как <script /="/">
,
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
,
Это потому, что TAG СКРИПТА не является пустым элементом.
В HTML-документе - VOID ELEMENTS вообще не нужен закрывающий тег!
В xhtml все является универсальным, поэтому все они требуют завершения, например, "закрывающий тег"; В том числе br, простой разрыв строки, как <br></br>
или его стенография <br />
,
Однако элемент Script никогда не является пустым или параметрическим элементом, потому что тег script, прежде всего, является инструкцией браузера, а не объявлением описания данных.
Как правило, инструкция семантического завершения, например, "закрывающий тег", требуется только для обработки инструкций, семантика которых не может быть завершена последующим тегом. Например:
<H1>
семантика не может быть прекращена следующим <P>
потому что он не несет достаточно своей собственной семантики, чтобы переопределить и, следовательно, завершить предыдущий набор команд H1. Несмотря на то, что он сможет разбить поток на новую строку абзаца, он недостаточно "силен", чтобы переопределить текущий размер шрифта и высоту стиля строки, стекающую по потоку, то есть вытекающую из H1 (потому что у P его нет).
Вот как и почему была изобретена сигнализация "/" (завершение).
Общий тег прекращения без описания, как < />
, было бы достаточно для любого падения с встречного каскада, например: <H1>Title< />
но это не всегда так, потому что мы также хотим иметь возможность "вложения", множественных промежуточных тегов потока: разделение на потоки перед переносом / падением на другой каскад. Как следствие, общий терминатор, такой как < />
не сможет определить цель свойства для прекращения. Например: <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 - это совершенно другой зверь; обосновывается; и поэтому разумно держать их отдельно.
Разница между "истинным XHTML", "поддельным 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
) расширение ( спасибо Алеку за этот совет).
Простой современный ответ заключается в том, что тег обозначен как обязательный таким образом
Пропуск тега Нет, и начальный, и конечный тег являются обязательными.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script