Linter Rule: Require explicit closing tags
Rule: html-require-closing-tags
Description
Disallow the omission of optional closing tags for HTML elements where the closing tag is technically optional according to the HTML specification. This rule flags elements that have an HTMLOmittedCloseTagNode as their close tag.
Rationale
While HTML allows certain closing tags to be omitted (implicitly closed by sibling elements or parent closing), explicit closing tags improve code readability and maintainability. They make the document structure clear at a glance and reduce ambiguity about where elements end.
Explicit closing tags also:
- Make templates easier to understand for developers unfamiliar with HTML's implicit closing rules
- Reduce potential for subtle bugs when refactoring or moving code
- Improve consistency across the codebase
- Make diffs cleaner when adding content to elements
Elements with Optional Closing Tags
This rule would flag elements that have omitted closing tags:
<li>- list items<dt>,<dd>- definition list terms and descriptions<p>- paragraphs<option>,<optgroup>- select options and groups<thead>,<tbody>,<tfoot>- table sections<tr>- table rows<td>,<th>- table cells<colgroup>- table column groups<rt>,<rp>- ruby annotations
Examples
✅ Good
Explicit closing tags:
erb
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>erb
<dl>
<dt>Term 1</dt>
<dd>Definition 1</dd>
<dt>Term 2</dt>
<dd>Definition 2</dd>
</dl>erb
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
</tr>
</tbody>
</table>erb
<select>
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</select>erb
<div>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</div>🚫 Bad
Omitted closing tags (implicitly closed):
erb
<ul>
<li>Item 1Element `<li>` at (2:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</li>` closing tag at (3:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <li>Item 2Missing explicit closing tag for `<li>`. Use `</li>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<li>` at (3:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</li>` closing tag at (4:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <li>Item 3Missing explicit closing tag for `<li>`. Use `</li>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<li>` at (4:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</li>` closing tag at (5:0) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors)</ul>Missing explicit closing tag for `<li>`. Use `</li>` instead of relying on implicit tag closing. (html-require-closing-tags)erb
<dl>
<dt>Term 1Element `<dt>` at (2:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</dt>` closing tag at (3:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <dd>Definition 1Missing explicit closing tag for `<dt>`. Use `</dt>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<dd>` at (3:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</dd>` closing tag at (4:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <dt>Term 2Missing explicit closing tag for `<dd>`. Use `</dd>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<dt>` at (4:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</dt>` closing tag at (5:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <dd>Definition 2Missing explicit closing tag for `<dt>`. Use `</dt>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<dd>` at (5:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</dd>` closing tag at (6:0) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors)</dl>Missing explicit closing tag for `<dd>`. Use `</dd>` instead of relying on implicit tag closing. (html-require-closing-tags)erb
<table>
<thead>Element `<thead>` at (2:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</thead>` closing tag at (6:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <tr>Element `<tr>` at (3:5) has its closing tag omitted. While valid HTML, consider adding an explicit `</tr>` closing tag at (6:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <th>Header 1Element `<th>` at (4:7) has its closing tag omitted. While valid HTML, consider adding an explicit `</th>` closing tag at (5:6) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <th>Header 2Missing explicit closing tag for `<th>`. Use `</th>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<th>` at (5:7) has its closing tag omitted. While valid HTML, consider adding an explicit `</th>` closing tag at (6:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <tbody>Missing explicit closing tag for `<thead>`. Use `</thead>` instead of relying on implicit tag closing. (html-require-closing-tags)Missing explicit closing tag for `<tr>`. Use `</tr>` instead of relying on implicit tag closing. (html-require-closing-tags)Missing explicit closing tag for `<th>`. Use `</th>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<tbody>` at (6:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</tbody>` closing tag at (10:0) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <tr>Element `<tr>` at (7:5) has its closing tag omitted. While valid HTML, consider adding an explicit `</tr>` closing tag at (10:0) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <td>Cell 1Element `<td>` at (8:7) has its closing tag omitted. While valid HTML, consider adding an explicit `</td>` closing tag at (9:6) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <td>Cell 2Missing explicit closing tag for `<td>`. Use `</td>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<td>` at (9:7) has its closing tag omitted. While valid HTML, consider adding an explicit `</td>` closing tag at (10:0) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors)</table>Missing explicit closing tag for `<tbody>`. Use `</tbody>` instead of relying on implicit tag closing. (html-require-closing-tags)Missing explicit closing tag for `<tr>`. Use `</tr>` instead of relying on implicit tag closing. (html-require-closing-tags)Missing explicit closing tag for `<td>`. Use `</td>` instead of relying on implicit tag closing. (html-require-closing-tags)erb
<select>
<option>Option 1Element `<option>` at (2:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</option>` closing tag at (3:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <option>Option 2Missing explicit closing tag for `<option>`. Use `</option>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<option>` at (3:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</option>` closing tag at (4:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <option>Option 3Missing explicit closing tag for `<option>`. Use `</option>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<option>` at (4:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</option>` closing tag at (5:0) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors)</select>Missing explicit closing tag for `<option>`. Use `</option>` instead of relying on implicit tag closing. (html-require-closing-tags)erb
<div>
<p>Paragraph 1Element `<p>` at (2:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</p>` closing tag at (3:2) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors) <p>Paragraph 2Missing explicit closing tag for `<p>`. Use `</p>` instead of relying on implicit tag closing. (html-require-closing-tags)Element `<p>` at (3:3) has its closing tag omitted. While valid HTML, consider adding an explicit `</p>` closing tag at (4:0) for clarity, or set `strict: false` to allow this. (`OMITTED_CLOSING_TAG_ERROR`) (parser-no-errors)</div>Missing explicit closing tag for `<p>`. Use `</p>` instead of relying on implicit tag closing. (html-require-closing-tags)