CSS-live.ru

«Не закрывайте теги!»

С таким провокационным призывом на днях обратился к своим читателям в Твиттере не кто-нибудь, а Таб Аткинс, главный редактор львиной доли спецификаций CSS. Конечно, речь шла не о любых тегах, а об опциональных (необязательных), которые разрешает не ставить сам стандарт HTML. Но всё равно призыв Таба многих шокировал, очень уж вразрез он шел со всем, чему нас учили с самого начала веб-карьеры.

Может, Таб просто всех троллил? Или же в его совете есть рациональное зерно? Попробуем непредвзято разобраться.

Какие теги можно не закрывать?

Так и хочется воскликнуть «Никакие!» :). Но давайте всё-таки обратимся к стандарту. Он разрешает опускать не только 19 закрывающих тегов, но и 5 открывающих. Все они, вместе с условиями, когда это можно делать, явно перечислены в целом одном страшно секретном разделе 12.1.2.4. И еще 14 тегов закрывать просто нельзя.

В таблицах ниже я попытался максимально упростить формулировку условий из спецификации (если где-то перестарался — прошу поправить):

Необязательные открывающие теги

Тег Когда можно не писать
<html> Если перед ним не идет <!-- комментарий -->
<head> Если перед ним не идет <!-- комментарий -->
<body> Если body начинается не с <!-- комментария -->, пробела, либо одного из тегов, который может быть и в head
<tbody> Перед <tr>, если перед ним нет незакрытого thead, tfoot или другого tbody
<colgroup> Перед <col>, если перед ним нет незакрытого другого colgroup

Нельзя опускать открывающий тег, если у него есть какие-либо атрибуты (напр. lang для <html>). Также открывающий <body> необходим, если его первым потомком должен быть script, link или другой элемент, который может быть и в head — иначе он попадет именно туда.

Необязательные закрывающие теги

Тег Когда можно не писать
</html> Если после него не идет <!-- комментарий -->
</head> Если после него не идет <!-- комментарий --> или пробел
</body> Если после него не идет <!-- комментарий -->
</li> Перед <li> или </ul>/</ol>
</dt> Перед <dt> или <dd>
</dd> Перед <dt>, <dd> или концом родителя
</p> Перед открывающим тегом любого не-фразового потокового («блочного» по-старому:) элемента, либо закрывающим тегом родительского элемента (если у того не прозрачная модель контента)
</rt> и </rp> Перед <rt>, <rp> или </ruby>
</optgroup> Перед <optgroup> или </select>
</option> Перед <option>, <optgroup>, </optgroup> или </select>
</colgroup> Если после него не идет <!-- комментарий --> или пробел
</caption> Если после него не идет <!-- комментарий --> или пробел
</thead> Перед <tbody> или <tfoot>
</tbody> Перед другим <tbody>, <tfoot> или </table>
</tfoot> Перед </table>
</tr> Перед <tr> или концом родителя
</td> и </th> Перед <td>, <th> или концом родителя

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

У правила для <p> общая логика похожа, но оно сложнее и потому стоит особняком (мы к нему еще вернемся).

А условие про HTML-комментарий означает лишь требование предсказуемости итоговой DOM. Например, что без явного тега нельзя вставить этот комментарий снаружи элемента. Это всё равно не будет ошибкой, просто в итоговой DOM комментарий окажется внутри него.

Теги, закрывать которые нельзя

Это пустые (void) элементы: area, base, br, col, embed, hr, img, input, link, meta, param, source, track, wbr.

Многие поспешат возразить: «Это же самозакрывающие(ся) теги, у них свой способ закрытия — слеш перед >!». Что ж, их ждет сюрприз: в HTML этот слеш… не значит ничего! Он не считается ошибкой, чтобы было легче переходить с XHTML, но «самозакрытыми», точнее, не требующими закрытия, их делает не слеш, а «зашитый» в алгоритм парсинга список этих пустых элементов. И «закрыть» по аналогии, скажем, <div /> нельзя — для HTML это будет открывающий тег (притом уже с ошибкой). Только для SVG- и MathML-элементов (напр. <g />) этот слеш означает честное «самозакрытие» (т.е. сокращение для <g></g>).

Аргументы против незакрытия тегов

«Это невалидный код!»

Необязательные теги — часть стандарта HTML. Значит, код, использующий их по правилам, валиден (точнее, соответствует этому стандарту). Так что это — невалидный аргумент:)

Нельзя полагаться на механизм исправления ошибок в браузерах

Вообще-то, в HTML5 алгоритм исправления ошибок «зашит» в стандартный алгоритм парсинга, и все браузеры мамой клянутся, что соблюдают этот стандарт. Так что ошибочная запись <a href="...">раз<a href="...">два</a> везде даст две ссылки подряд, а не вложенную ссылку.

Но я согласен: полагаться на ошибочное поведение чего бы то ни было — очень, очень плохая идея.

Вот только разрешенные необязательные теги — не ошибка. А хоть и непривычный, но вариант правильного HTML-кода. И этот аргумент валидный — но мимо:)

Хрупкость

Часто говорят, что код с незакрытыми тегами легче сломать чем-то непредвиденным. Но давайте поищем конкретную ситуацию, где это проявится.

Например, вдруг в нашем шаблоне появился HTML-комментарий. Давайте честно: на что может повлиять, добавится этот комментарий внутрь неявного <head> или <body> или снаружи?

Или возьмем динамически генерируемый список. Если внутрь нашего пункта списка попадет другой <li>, то пункт развалится на два — но это произойдет независимо от того, явно он был закрыт или неявно.

Еще в <head>...</head> нередко попадает то, что не может там находиться. Например, что-то, что браузер считает выводимым на экран текстом (в подключаемых PHP-шаблонах это часто могла быть BOM-метка). Это сразу же неявно закрывает </head> и открывает <body>. И снова независимо от того, где и как стояли соотв. теги.

Другое дело, если кто-то возьмет и не закроет другой тег, скажем, </div> или тот же </a>. Но это уже проблема нарушения стандарта (равно как и закрытие тега в неподходящем месте!). Ее решение — валидация кода (в т.ч. автоматическая, на этапе сборки/CI). И оно снова не зависит от наличия/отсутствия необязательных тегов!

Может быть, в комментариях вы подскажете более убедительный пример, где именно легально незакрытый тег будет причиной хрупкости?

Несовместимость с XML (и JSX)

Факт: HTML и XML — разные языки (а JSX — вообще де-факто третий, хоть отчасти и «косплеит» XML внешне), и правила у них разные. Если нужно соблюсти и те, и те, то, конечно, без явного закрытия тегов никак. Другой вопрос, где и зачем сегодня нужна совместимость HTML с XML?..

Несовместимость с редакторами и IDE

Многие редакторы кода при подсветке синтаксиса, сворачивании ветвей и т.п. привязываются к явным закрывающим тегам. Некоторые даже закрывают их автоматически. Что ж, правила инструментов тоже желательно соблюдать. Только стоит отличать их от правил языка.

Несовместимость с кодстайлами и рабочими процессами

Аналогично: если в проекте принят какой-то дополнительный стандарт оформления кода помимо синтаксической корректности HTML — будь то лимит длины строк или требование явно закрывать теги — его тоже надо соблюдать. Но он не должен становиться самоцелью: если на его соблюдение уходит слишком много сил и он мешает использовать какую-то стандартную возможность языка, удобную для конкретной задачи — может, легче будет его пересмотреть или перейти на другой?

Трудность чтения

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

Сложность правил для запоминания

Таблицы с правилами, когда какой тег можно не закрывать, выглядят внушительно. И это я еще их упростил! Даже сам Таб Аткинс в исходном твиттерском треде запутался, какие теги неявно закрывают <p>, а разница между случаями, когда открывающий <body> обязателен, а когда нет, навскидку еще менее интуитивна. Не лучше ли вместо этого вот всего запомнить одно простое правило «всегда закрывай все теги!»?

Увы: одним простым правилом от HTML не отделаешься:). Как минимум 14 исключений — пустые элементы, которые закрывать нельзя — помнить всё равно надо. А что еще важнее, явное закрытие тега не гарантирует, что элемент действительно закончится именно в этом месте (мы уже мельком видели пару примеров, дальше будет больше). Но разве в других языках нет таких «странных» правил? Одна таблица приведения типов в JS чего стоит.

Простота записи поощряет бардак в коде

Занятно, что этот аргумент часто сочетается с предыдущим.

Да, код в стиле «ляпнул открывающий тег и вперёд» может показаться небрежным и «несерьезным». Но это тоже вопрос привычки. Пример обратного — Markdown: одна звездочка — один пункт списка и никаких «закрывающих тегов», при этом в коде полный порядок и читать его — одно удовольствие. Но да, Markdown и HTML — тоже разные языки:)

В любом случае, закрыть тег много ума не надо не так уж сложно (тем более часто это на автомате делает IDE). Сложнее поставить его там, где надо, по правилам языка. Но не поставить его там, где можно по стандарту и уместно по задаче — сложность примерно сопоставимая. Ниже мы увидим, что чтобы писать правильный HTML — хоть с явными тегами, хоть без — его всё равно придется знать.

Явное лучше неявного

Безусловно!

Когда между ними действительно есть выбор.

Увы, с HTML это не всегда так (подробности чуть ниже).

Аргументы за незакрытие тегов

Всего лишь сокращенная запись

В XML были две равнозначные записи элемента без содержимого — полная (<tag></tag>) и сокращенная (<tag/>). Вторая почему-то до сих пор популярна даже в HTML, хотя там этот слеш ничего не значит (см. выше).

Точно так же и в HTML по сути есть две равнозначные записи конструкции «конец элемента и начало следующего» — полная (напр. </p><p>) и сокращенная (напр. <p>). Т.е. формально в обоих случаях эти теги закрыты, просто не всегда очевидным образом.

Экономия трафика

Принцип прост: если не видно разницы — зачем платить писать (и гонять по сети) больше. Древний «гайд» по оформлению HTML/CSS от Google так этот совет и формулировал: «байты — деньги».

Это может быть и вправду актуально для Гугла с его объемами трафика. Для остальных это скорее всего экономия на спичках. Особенно с gzip или еще лучшими новыми алгоритмами сжатия. Но протестировать всё равно не помешает:)

Экономия памяти

Любые символы между тегами — включая пробелы и переносы строк — попадают в DOM в виде текстовых нод. В эпоху верстки инлайн-блоками эти ноды-пробелы доставляли немало хлопот (и одним из решений как раз было не закрывать теги:). Сейчас это неактуально, но сами ноды никуда не делись. Так что в DOM списка с закрытыми тегами <li> на самом деле будет вдвое больше нод, чем в DOM списка с незакрытыми (при обычном форматировании исходника, без минификации):

See the Pen
poJKLzb
by Ilya Streltsyn (@SelenIT)
on CodePen.

И эти лишние ноды — полноценные DOM-объекты, с кучей свойств и методов. Другой вопрос, так ли много места они занимают в памяти и сильно ли это влияет на производительность страницы (как всегда, надо тестировать и измерять!)

По правде, этот аргумент выходит не столько за незакрытие тегов, сколько за минификацию кода для продакшна, с убиранием всех ненужных пробелов и т.д. Хотя тот же минификатор можно настроить и на вырезание необязательных тегов. Если тесты покажут, что от этого есть толк. Добавлено 26.03.2020: к счастью, проблемы минификаторов 10-летней давности, не всегда умевших отличить необязательный тег от обязательного, остались в прошлом – нынешняя версия html-minifier использует честный HTML5-парсер и, если не злоупотреблять опциями с «невалидным HTML» на выходе, ничего не сломает.

«Защита от дурака»

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

See the Pen
KKpGBqO
by Ilya Streltsyn (@SelenIT)
on CodePen.

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

Удобство чтения

Как ни странно, некоторым проще читать код без закрывающих тегов. Для людей программистского склада, привыкших держать все сущности в контейнерах, это звучит дико, но тем, кто больше работает с текстом, часто привычнее думать о разделителях абзацев, пунктов списка и ячеек таблицы. Именно разделители используются в редакторах типа Word, вышеупомянутом Markdown… и HTML задумывался так же (в одном из ранних черновиков те же <p>, <li> и т.п. так и были одиночными разделителями, вроде <br>).

Сравните две разметки таблицы с внешне идентичным результатом:

<table>
  <caption>Цены на продукты<caption>
  <thead>
    <tr>
      <th>Продукт</th>
      <th>Февраль</th>
      <th>Март</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Гречка</th>
      <td>80</td>
      <td>120</td>
    </tr>
    <tr>
      <th>Соль</th>
      <td>5</td>
      <td>15</td>
   </tr>
   <tr>
     <th>Икра</th>
     <td>1500</td>
     <td>900</td>
   </tr>
  </tbody>
</table>

<table>
  <caption>Цены на продукты
  <thead>
    <tr>
      <th>Продукт <th>Февраль <th>Март
  <tbody>
    <tr>
      <th>Гречка  <td>80      <td>120
    <tr>
      <th>Соль    <td>5       <td>15
    <tr>
      <th>Икра    <td>1500    <td>900
</table>

Правда, тут повезло, что вся таблица и текст в ячейках короткие, а хороший кодстайл должен быть универсальным и не зависеть от везения..:)

Лучшее понимание специфики HTML и защита от сюрпризов

Этот аргумент Таба я вынес отдельно, чтобы он не затерялся (и выделил ключевые, на мой взгляд, слова жирным):

Еще одна причина привыкнуть к этому [не ставить необязательные теги] — то, что HTML-парсер будет делать это [достраивать DOM] в любом случае, и вы сможете заодно выучить соответствующие правила, так что не споткнетесь на этом. Если вы используете закрывающие теги с бездумным фанатизмом, вы можете *полагать*, что знаете, где заканчивается элемент, но окажетесь неправы!

Частый вопрос на форумах, StackOverflow, да и в жизни верстальщика: «Почему мой список внутри абзаца не отображается как надо?» Во всех руководствах по HTML <p>...</p> — пример блочного контейнера. С детства мы помним, что абзац — это «законченная мысль», так что если она включает в себя список чего-либо, подводку к нему и некий итог — логично, чтобы всё это было в одном абзаце. Вот открывающий <p>, вот список внутри, вот закрывающий </p>, всё закрыто в правильном порядке… Почему же в DOM-инспекторе список оказался снаружи абзаца?

Да, иногда привычка «мыслить контейнерами» и безоговорочно доверять явным тегам может оказать медвежью услугу не только новичку, маскируя неочевидное поведение парсера. А новичку здесь и валидатор мало поможет: «Найден закрывающий тег без открывающего…» — ну как же его нет, когда вот он? Ладно, <p> допускает лишь «фразовое» («строчное», по-старому) содержимое, а список к нему не относится — но ведь другие теги, даже насквозь «строчный» <span>, от точно такой же неправильной вложенности не рвутся!

А вот знание, что закрывающий </p> необязателен, и открывающий тег любого «блочного» (по-старому) элемента — его стандартный эквивалент, эту ситуацию бы предотвратило. Мы бы сразу обернули эту «мысль» не в <p>...</p>, а во что-то другое, без неявного закрытия — хоть <div>. Что, кстати, рекомендует и спецификация.

Аргумент против тегов вообще

Браузерам, по большому счету, вообще плевать на теги. Они отображают не разметку, а DOM, и оперируют лишь DOM-элементами и их свойствами. DOM может строиться по-разному, и в современном мире куда чаще она строится скриптами, а не парсится прямо из разметки. Разметка — лишь один из способов описания будущей DOM в текстовом формате, в принципе не лучший для машины, зато более понятный для человека.

А люди в наше время тоже редко пишут разметку руками. Чаще эту скучную механическую работу за нас делают инструменты — препроцессоры, шаблонизаторы и всё такое прочее. И это их задача — ставить те теги, которые надо, где надо и как надо, чтобы парсеры, со всеми их странностями и документированными причудами, всё правильно поняли. Их, а не наша.

Не в том ли причина многих проблем нынешней веб-отрасли, что истинную природу веб-платформы от разработчиков всю их жизнь вольно или невольно скрывают — сначала за тегами (и пустяками типа их регистра, словно мы до сих пор в 90-х), а затем за абстракциями фреймворков?..

заставка из Матрицы

Заключение

Думаю, подытожить эту статью можно примерно так:

  1. Необязательные теги — не ошибка, не «магия», не «браузерная самодеятельность» и т.п. (как часто считают), а документированная особенность стандарта. По сути — еще один инструмент HTML, такой же, как и закрывающие теги. Можно спорить, входят ли они в «The good parts» языка HTML (скорее всего нет!:), но в некоторых задачах (напр. для экстремальной оптимизации) они могут быть полезны;
  2. Почти все валидные аргументы и за, и против необязательных тегов сводятся к двум фразам: «делайте, как вам удобнее», и «делайте, как у вас (в проекте, в команде, в настройках окружения и т.д.) заведено». Ну и еще «смотрите по задаче и тестируйте!».

Поэтому в подавляющем большинстве случаев все необязательные теги лучше всё-таки ставить. Не потому, что «Так Надо, Ибо Воистину ©», или будто это автоматически «сделает код надежнее», а лишь потому, что:

  • так удобнее и понятнее большинству разработчиков;
  • так настроено по умолчанию большинство инструментов.

Код должен решать свою задачу. Задача исходников — не столько инструкция для браузеров (им-то стиль кода не важен), сколько коммуникация между разработчиками. Понятнее для большинства — коммуникация лучше.

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

А вообще в веб-платформе масса вещей, куда более важных, чем стиль написания тегов или спор между табами и пробелами. Та же доступность хотя бы!

И всё-таки, к одному из аргументов я хотел бы вернуться. В общем-то, ради него я и затеял эту статью:)

Веб-платформа большая и сложная. В ней много неизвестного и непонятного — даже для авторов спецификаций. Сложность и неизвестность пугает. Это естественно. И людям естественно успокаивать себя, отгораживаться от своих страхов приметами и ритуалами. Сплюнул через левое плечо — «беда обойдет». Успел потрогать пуговицу перед черной кошкой — «неудача отступит». Написал тег со слешем — «код не сломается». И т.п.

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

А лучший способ изучить что-либо — эксперимент. И у веба огромное преимущество перед, скажем, ядерной физикой или генетикой, что здесь в экспериментах «для себя» иногда можно нарушать правила и смотреть, что из этого выйдет — ничего действительно страшного не случится. Зато станет понятнее, почему правила именно такие. И вообще — а правила ли это (а не реликт совсем другой эпохи с совсем другими ограничениями, скажем — это я не про закрытие тегов, а абстрактно:)

Так что не бойтесь экспериментировать! И пусть с каждым днем всё больше особенностей веб-платформы становится для вас не странной «магией», а понятным и предсказуемым инструментом. Который при ненадобности всегда можно отложить в дальний ящик, но иногда, если задача того потребует, использовать на радость себе и пользователям.

P.S. Это тоже может быть интересно:

15 комментариев

  1. Отлично написано!

    Например, вдруг в нашем шаблоне появился HTML-комментарий. Давайте честно: на что может повлиять, добавится этот комментарий внутрь неявного <head> или <body> или снаружи?

    Некоторые популярные фреймврки, такие как vue например — отмечают места вставки тегов служебными комментариями

  2. Любые символы между тегами — включая пробелы и переносы строк — попадают в DOM в виде текстовых нод. В эпоху верстки инлайн-блоками эти ноды-пробелы доставляли немало хлопот (и одним из решений как раз было не закрывать теги:). Сейчас это неактуально, но сами ноды никуда не делись. Так что в DOM списка с закрытыми тегами <li> на самом деле будет вдвое больше нод, чем в DOM списка с незакрытыми (при обычном форматировании исходника, без минификации):

    К сожалению, из примера плохо видно откуда появляются эти текстовые узлы. Я бы проиллюстрировал этот абзац следующим образом.

    1. Спасибо, отличная иллюстрация! Я попробовал сделать чуть нагляднее сам пример.

      1. Прекрасная тема )) я думал никто не парится такими ) а вот нет! Я вот очень парюсь пробелами и переводами строк и кавычками в атрибутах. Вопрос: 1) если между закрытием одного и открытием следующего типа </p><p> не использовать ни перевод каретки на пробелы — ноды DOM возникают? 2) А перевод каретки без пробелов </p>chr(13)chr(10)<p> создаёт DOM ноду или нет?

        1. В первом случае не возникнет, во втором возникнет. Символы перевода строки и возврата каретки тоже считаются пробельными символами, т.е. непустой строкой.

  3. Другой вопрос, где и зачем сегодня нужна совместимость HTML с XML?

    Как где и зачем? Парсеров XML как грязи в любом языке программирования. А нормальных парсеров HTML почти нет. Да и не удивительно с такими закидонами, что в спецификации нашкрябали. Поэтому проще использовать XML парсеры, они надежнее как-то, предсказуемее по поведению и широки по функциональности.

    1. Если вы будете передавать свой с XHTML-код с типом содержимого application/xhtml+xml, то он будет разбираться с помощью XML-парсера. Недостатком такого подхода является то, что это приведет к запуску «драконовской» обработки ошибок. Т.е. если в разметке содержится хотя бы одна синтаксическая ошибка, то весь документ будет признан недействительным и пользователь увидит на экране лишь сообщение об ошибке. Если для статических сайтов можно гарантировать 100% отсутствие синтаксических ошибок, то для динамических сайтов это сделать намного труднее.

      Именно из-за «драконовской» обработки ошибок XHTML 1.1 и XHTML5 не получили широкого распространения. Более подробную информацию по этой теме вы можете прочитать в книге Марка Пилгрима «Dive Into HTML5».

  4. С таким провокационным призывом на днях обратился к своим читателям в Твиттере не кто-нибудь, а Таб Аткинс, главный редактор львиной доли спецификаций CSS.

    Нет ничего шокирующего в этом призыве, просто наследие XHTML постоянно дает о себе знать. Уже прошло больше десяти лет, как была свернута работа над XHTML 2.0, но мы по-прежнему боимся незакрытых опциональных тегов и значений атрибутов без кавычек.

    Возможность не закрывать теги у нас есть уже очень давно. Например, уже в начале нулевых данный функционал поддерживался инструментом HTML Tidy, который разрабатывался при поддержке W3C. В консольном приложении за этот функционал отвечал флаг –omit, а в библиотеке — опция hide-endtags. Современная версия библиотеки также поддерживает этот функционал.

    Вообще, на русском языке доступно мало информации по этой теме. Например, на английском полгода назад вышла хорошая статья Йенса Оливера Мейерта «Optional HTML: Everything You Need to Know».

    Я считаю, что во время разработки всегда следует закрывать теги и использовать кавычки в атрибутах. Опциональный HTML должен удаляться автоматизированными средствами (HTML-минификаторы или HTML Tidy) перед публикацией кода на продакшене.

    1. Спасибо за отличный комментарий!

      Возможность не закрывать теги у нас есть уже очень давно

      Я бы сказал, что для <p>, <li> и т.п. она появилась раньше, чем мысль их закрывать:). Ранние примеры HTML чаще оперировали ими как разделителями, представление о них как о контейнерах стало основным лишь с появлением т.н. «Dynamic HTML»:). Другое дело, что до HTML5 бывала неоднозначность: честных SGML-правил никто (кроме W3C-валидатора) не соблюдал, а в разных браузерах бывали разные эвристики, отчего, напр., в IE вставить таблицу в абзац получалось, а в Мозилле (еще не Firefox) или Опере – нет. Теперь проще, потому что есть единый для всех стандартный алгоритм парсинга (если инструмент его соблюдает, конечно).

      на русском языке доступно мало информации по этой теме

      Отчасти поэтому я и решил заполнить пробел. Статья Йенса Майерта действительно хороша, но я подумал, что будет полезно чётче разделить теги, которые ставить нельзя и теги, которые можно не ставить, а также хотя бы кратко сказать про условия для этого (Майерт только «посылает» в спецификацию:). Вот тему опциональных атрибутов я не затрагивал, во-первых, потому что статья и так вышла длинной, а во-вторых, я не знаю случая, когда от закавычивания атрибутов бывает вред. А проблемы от механического закрытия тегов и излишнего доверия к ним встречал.

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

      Полностью согласен со второй частью, но первую сформулировал бы не так категорично. Я считаю, что каждый символ кода должен решать задачу. В подавляющем большинстве случаев одна из задач кода – быть понятным для большинства других разработчиков, и явные теги и кавычки в этой задаче помогают. Если в работе используется промежуточный XML-стек, то впридачу к этому надо соблюдать и все принципы «разметки-полиглота» (помнить, какие элементы можно «самозакрывать», а какие нет, и т.д.). И т.п.

      Но когда задача – разобраться для себя, что происходит в коде и почему, понять эту странную «магию» (даже для того, чтобы в дальнейшем успешнее ее избегать!) – любые лишние символы могут скорее отвлечь и запутать. Поэтому новичкам при обучении лично я рекомендовал бы-таки попробовать писать код и так, и эдак. Чтобы потом писать читаемый код осознанно, с пониманием, в чем его плюсы и что в нем на что влияет, а не механически повторять непонятные действия из того самого иррационального страха:)

      P.S. Прошу прощения за техническую накладку, из-за которой комментарий не сразу отобразился

      1. Насколько я помню, опциональные теги впервые были явно описаны в спецификации HTML 3.2:

        In practice, the HTML, HEAD and BODY start and end tags can be omitted from the markup as these can be inferred in all cases by parsers conforming to the HTML 3.2 DTD.

        The paragraph element requires a start tag, but the end tag can always be omitted.

        The LI element is used for individual list items. The end tag for LI elements can always be omitted.

        Each table row is contained in a TR element, although the end tag can always be omitted. Table cells are defined by TD elements for data and TH elements for headers. Like TR, these are containers and can be given without trailing end tags.

        А в спецификации HTML 2.0 эта возможность была показана только в примерах:

        <H1>This Heading Precedes the Paragraph</H1>
        <P>This is the text of the first paragraph.
        <P>This is the text of the second paragraph. Although you do not
        need to start paragraphs on new lines, maintaining this
        convention facilitates document maintenance.</P>
        <P>This is the text of a third paragraph.</P>

        и

        <OL>
        <LI>Click the Web button to open URI window.
        <LI>Enter the URI number in the text field of the Open URI
        window. The Web document you specified is displayed.
        <ol>
        <li>substep 1
        <li>substep 2
        </ol>
        <LI>Click highlighted text to move from one link to another.
        </OL>

        1. По поводу HTML 2.0 я ошибся, там тоже это было описано явно:

          … Additionally, the end tags of some other elements, such as Paragraph (`</P>’), List Item (`</LI>’), Definition Term (`</DT>’), and Definition Description (`</DD>’) elements, may be omitted.

          1. В самом первом письме сэра Тима Бернерса-Ли, с которого начался HTML, тоже говорилось

            The format is simply
            <P>
            (In SGML terms, paragraph elements are transmitted in minimised form).

            Для пунктов списков это не сказано явно, но видно по примерам. Ну и в заготовке для IETF они все прямо в DTD объявлялись как «empty», т.е. как одиночные теги а-ля <br>

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.