Sobre este problema HTML
Em HTML, os elementos dividem-se em duas categorias relativamente ao seu modelo de conteúdo: elementos vazios e elementos não vazios. Elementos vazios como <img>, <br>, <hr>, <input>, <meta>, e <link> não podem ter qualquer conteúdo e nunca precisam de uma tag de fecho. Elementos não vazios como <div>, <p>, <span>, <select>, <textarea>, e <script> podem (ou devem) conter conteúdo e requerem tanto uma tag de abertura como uma tag de fecho.
Quando escreve <div /> ou <select />, pode esperar que o browser o trate como um elemento completo e autossuficiente — similar ao modo como XML ou XHTML o interpretaria. No entanto, o parser HTML não funciona desta forma. De acordo com o WHATWG HTML Living Standard, o /> num elemento não vazio é simplesmente ignorado. O browser trata <div /> como apenas <div> — uma tag de abertura sem uma tag de fecho correspondente. Isto pode levar a problemas estruturais graves no seu documento, pois o browser continuará à procura de conteúdo e de uma tag de fecho, potencialmente absorvendo elementos subsequentes como filhos.
Este problema surge frequentemente quando os programadores estão habituados a frameworks como React (JSX), onde a sintaxe <Component /> é padrão, ou quando vêm de um contexto XML/XHTML onde qualquer elemento pode ser auto-fechado. Também aparece quando os programadores acreditam erroneamente que um elemento sem conteúdo pretendido pode ser auto-fechado em HTML.
As consequências podem ser significativas. A árvore DOM do browser pode acabar drasticamente diferente do que você pretendia, causando problemas de layout, funcionalidades quebradas, e questões de acessibilidade. Por exemplo, uma tag <script /> auto-fechada não se comportará como esperado — o browser tratará tudo após ela como o conteúdo do script até encontrar uma tag de fecho </script> nalgum outro lugar do documento, efetivamente escondendo o conteúdo visível da sua página.
Como corrigir
- Remova a barra final da tag de abertura do elemento não vazio.
- Adicione uma tag de fecho adequada imediatamente após a tag de abertura se o elemento deve estar vazio, ou após o seu conteúdo.
A lista completa de elementos vazios em HTML é: <area>, <base>, <br>, <col>, <embed>, <hr>, <img>, <input>, <link>, <meta>, <source>, <track>, e <wbr>. Apenas estes elementos podem usar sintaxe de fecho automático (e mesmo para estes, o / é opcional em HTML).
Exemplos
Incorreto: sintaxe de fecho automático em elementos não vazios
<div />
<select />
<option value="1">one</option>
</select>
<span />
<textarea />
<script src="app.js" />
Cada um destes irá desencadear o aviso. O validador ignora a barra e trata-os como tags de abertura, significando que o browser espera conteúdo e uma tag de fecho a seguir.
Correto: usar tags de fecho adequadas
<div></div>
<select>
<option value="1">one</option>
</select>
<span></span>
<textarea></textarea>
<script src="app.js"></script>
Correto: sintaxe de fecho automático em elementos vazios
Elementos vazios podem opcionalmente usar a barra final. Ambas as formas abaixo são válidas:
<!-- Com barra final opcional -->
<img src="photo.jpg" alt="A photo" />
<br />
<input type="text" name="username" />
<!-- Sem barra final (igualmente válido) -->
<img src="photo.jpg" alt="A photo">
<br>
<input type="text" name="username">
Uma armadilha subtil: <script />
Este exemplo demonstra um dos casos mais perigosos desta questão:
<!-- Incorreto: o browser trata tudo após isto como conteúdo de script -->
<script src="app.js" />
<p>Este parágrafo não será renderizado — é consumido como texto de script.</p>
<!-- Correto -->
<script src="app.js"></script>
<p>Este parágrafo renderiza normalmente.</p>
O browser interpreta a versão incorreta como uma tag <script> de abertura e lê toda a marcação subsequente como conteúdo de script até encontrar </script>, efetivamente escondendo o conteúdo da sua página e provavelmente produzindo erros de JavaScript.
Encontre problemas como este automaticamente
O Rocket Validator analisa milhares de páginas em segundos, detetando problemas HTML em todo o seu site.