You are not required to close your <p>, <li>, <img>, or <br> tags in HTML
134 points
2 days ago
| 44 comments
| blog.novalistic.com
| HN
tannhaeuser
6 hours ago
[-]
Guess what, you're not required to open <html>, <head>, or <body> either. It all follows from SGML tag inference rules, and the rules aren't that difficult to understand. What makes them appear magical is WHATWG's verbose ad-hoc parsing algorithm presentation explicitly listing eg. elements that close their parents originally captured from SGML but having become unmaintained as new elements were added. This already started to happen in the very first revision after Ian Hickson's initial procedural HTML parsing description ([1]).

I'd also wish people would stop calling every element-specific behavior HTML parsers do "liberal and tag-soup"-like. Yes WHATWG HTML does define error recovery rules, and HTML had introduced historic blunders to accomodate inline CSS and inline JS, but almost always what's being complained about are just SGML empty elements (aka HTML void elements) or tag omission (as described above) by folks not doing their homework.

[1]: https://sgmljs.sgml.net/docs/html5.html#tag-omission (see also XML Prague 2017 proceedings pp. 101ff)

reply
modeless
4 hours ago
[-]
HTML becomes pretty delightful for prototyping when you embrace this. You can open up an empy file and start typing tags with zero boilerplate. Drop in a script tag and forget about getElementById(); every id attribute already defines a JavaScript variable name directly, so go to town. Today the specs guarantee consistent behavior so this doesn't introduce compatiblity issues like it did in the bad old days of IE6. You can make surprisingly powerful stuff in a single file application with no fluff.

I just wish browsers weren't so anal about making you load things from http://localhost instead of file:// directly. Someone ought to look into fixing the security issues of file:// URLs so browsers can relax about that.

reply
indigodaddy
3 hours ago
[-]
Love the single file html tool paradigm! See https://simonwillison.net/2025/Dec/10/html-tools/

Opus and I have made a couple of really cool internal tools for work. It's really great.

reply
HarHarVeryFunny
3 hours ago
[-]
A workaround for the file:// security deny is to use a JavaScript file for data (initialized array) rather than something more natural like JSON.

Apparently JavaScript got grandfathered in as ok for direct access!

reply
carshodev
1 hour ago
[-]
I liked learning this so much that I created a VSCode Extension to enable goto clicking and autocomplete and errors for single page html files and type hover so I can properly use it when i am prototyping.

https://marketplace.visualstudio.com/items?itemName=carsho.h...

reply
circuit10
4 hours ago
[-]
Wow, I had never heard of that ID -> variable feature
reply
modeless
4 hours ago
[-]
Yeah it was hard to believe when I first learned about it, but it's true. I think I first found out when I forgot to put in a getElementById call and my code still worked.
reply
chmod775
3 hours ago
[-]
More specifically it becomes a property of window, which is the global object.

So <div id="hello"> becomes accessible as window["hello"], which means you can just directly write hello.innerText = "Hi!".

Since this may conflicts with any of the hundreds of other properties on window, it's generally not something that should be used.

Historically it wasn't too uncommon to see it, but since it doesn't work well with typescript, it's very rare now.

reply
AlienRobot
2 hours ago
[-]
You can make it work with typescript by declaring it as an HTMLElement without defining it.
reply
halapro
3 hours ago
[-]
It's been there since the beginning but it has several exceptions, like it's not available in strict mode and modules. Ask your ChatGPT if implied globals are right for you.
reply
BiteCode_dev
3 hours ago
[-]
Also window.document.forms gets you direct access to all forms, "name" automatically attach an attribute to the parents and "this" rebind to the current element on inline event handler.

The DOM API may have been very messy at creation, but it is also very handy and powerful, especially for binding to a live programming visual environment with instant remote update capabilities.

reply
halapro
3 hours ago
[-]
Speaking of forms: form.elements.username is my preferred way of accessing form fields. You can also use a field .form prop to access its connected form. This is fundamental when the field exists outside <form> ;)
reply
eastbound
2 hours ago
[-]
You mean there is bidirectional binding between form.elements.username and the UI value? Why did we need React! HTML should have IFs and FOR loops…
reply
marcosdumay
2 hours ago
[-]
> Someone ought to look into fixing the security issues of file:// URLs

If you mean full sandboxing of applications with a usable capability system, then yeah, someone ought to do that. But I wouldn't hold my breath, there's a reason why nobody did yet.

reply
carshodev
3 hours ago
[-]
Yes i love quickly creating tools in a single file, if the tool gets really complex I'll switch to a sveltekit Static site. I have a default css file I use for all of them to make it even quicker and not look so much like AI slop.

I think every dev should have a tools.TheirDomain.zzz where they put different tools they create. You can make so many static tools and I feel like everyone creates these from time to time when they are prototyping things. There's so many free options for static hosting and you can write bash deploy scripts so quickly with AI, so its literally just ./deploy.sh to deploy. (I also recommend writing some reusable logic for saving to local storage/indexedDB so its even nicer.)

Mine for example is https://tools.carsho.dev (100% offline/static tools, no monetization)

reply
SoftTalker
4 hours ago
[-]
What are the security issues of file:// URLs?
reply
williamcotton
3 hours ago
[-]

  fetch("file:///C:/Users/You/Documents/secrets.txt")
reply
SoftTalker
2 hours ago
[-]
As long as same-origin is enforced this is probably OK? I'm going to steal my own secrets?
reply
vedmakk
3 hours ago
[-]
"Chrome wants to access 'secrets.txt'. Allow | Deny"
reply
williamcotton
3 hours ago
[-]

  $ python -m http.server
reply
AlienRobot
2 hours ago
[-]
Imagine a very plausible situation. You have 1 HTML file at the top that wants to access hundreds of files in a subfolder. There is no way you can show Allow | Deny for every one of them. On the other hand, it's also possible for someone to take that file and put it in a folder like Documents or Downloads, so blanket allowing it access to siblings would allow access to all those files.

This could easily be solved by some simple contract like "webgame.html can only access files in a webpage/ subdirectory," but the powers that be deemed such thing not worth the trouble.

reply
pwdisswordfishy
5 hours ago
[-]
reply
tannhaeuser
4 hours ago
[-]
I guess you're replying to my comment because you were triggered by my last sentence. I wasn't criticizing you specifically, but yeah, in another comment you're writing

> It probably didn't help that XHTML did not offer any new features over tag-soup HTML syntax.

which unfortunately reaks of exactly the kind of roundabout HTML criticism that is not so helpful IMO. We have to face the possibility that most HTML documents have already been written at this point, at least if you value text by humans.

The CVEs you're referencing are due to said historic blunders allowing inline JS or otherwise tunneling foreign syntax in markup constructs (mutation XSSs are only triggered by serialising and reparsing HTML as part of bogus sanitizer libs anyway).

If you look at past comments of mine, you'll notice I'm staunchly criticizing inline JS and CSS (should always be placed in external "resources") and go as far as saying CSS or other ad-hoc item-value syntax should not even exist when attributes already serve this purpose.

The remaining CVE is made possible by Hickson's overly liberal rules for what's allowed or needs escaping in attributes vs SGML's much stricter rules.

reply
modeless
4 hours ago
[-]
Inline JS or CSS is fine if typed directly by humans. It's only a problem when generated. Generated resources should always be in separate files.

I like the flexibility of being able to make one file HTML apps with inline resources when I'm not generating code. But there should be better protections against including inline scripts in generated code unintentionally.

reply
skobes
3 hours ago
[-]
Omitting <body> can lead to weird surprises. I once had some JavaScript mysteriously breaking because document.body was null during inline execution.

Since then I always write <body> explicitly even though it is optional.

reply
HiPhish
11 hours ago
[-]
Serious question: why would you ever want to not close tags? It saves a couple of key strokes, but we have snippets in our editors, so the amount of typing is the same. Closed tags allow editors like Vim or automated tools to handle the source code easier; e.g. I can type `dit` in Vim to delete the contents of a tag, something that's only possible because the tag's content is clearly delimited. It makes parsing HTML easier because there are fewer syntax rules.

I learned HTML quite late, when HTML 5 was already all the rage, and I never understood why the more strict rules of XML for HTML never took off. They seem so much saner than whatever soup of special rules and exceptions we currently have. HTML 5 was an opportunity to make a clear cut between legacy HTML and the future of HTML. Even though I don't have to, I strive to adhere to the stricter rules of closing all tags, closing self-closing tags and only using lower-case tag names.

reply
pwdisswordfishy
11 hours ago
[-]
> I never understood why the more strict rules of XML for HTML never took off

Internet Explorer failing to support XHTML at all (which also forced everyone to serve XHTML with the HTML media type and avoid incompatible syntaxes like self-closing <script />), Firefox at first failing to support progressive rendering of XHTML, a dearth of tooling to emit well-formed XHTML (remember, those were the days of PHP emitting markup by string concatenation) and the resulting fear of pages entirely failing to render (the so-called Yellow Screen of Death), and a side helping of the WHATWG cartel^W organization declaring XHTML "obsolete". It probably didn't help that XHTML did not offer any new features over tag-soup HTML syntax.

I think most of those are actually no longer relevant, so I still kind of hope that XHTML could have a resurgence, and that the tag-soup syntax could be finally discarded. It's long overdue.

reply
xg15
7 hours ago
[-]
What I never understood was why, for HTML specifically, syntax errors are such a fundamental unsolvable problem that it's essential that browsers accept bad content.

Meanwhile, in any other formal language (including JS and CSS!), the standard assumption is that syntax errors are fatal, the responsibility for fixing lies with the page author, but also that fixing those errors is not a difficult problem.

Why is this a problem for HTML - and only HTML?

reply
notahacker
6 hours ago
[-]
HTML is a markup language to format text, not a programming or data serialization language so end users have always preferred to see imperfectly coded or incompletely loaded web pages imperfectly rendered over receiving a failure message, particularly on 90s dialup. Same applies to most other markup languages.

The web owes its success to having low barriers to entry and very quickly became a mixture of pages hand coded by people who weren't programmers, content produced by CMS systems which included stuff the content author didn't directly control and weren't necessarily reliable at putting tags into the right place, and third party widgets activated by pasting in whatever code the third party had given you. And browsers became really good at attempting to rendering erroneous and ambiguous markup (and for that matter were usually out of date or plain bad at rigidly implementing standards)

There was a movement to serve XHTML as XML via the application/xhtml+xml MIME type but it never took off because browsers didn't do anything with it except loading a user-hostile error page if a closing tag was missed (or refusing to load it at all in the case of IE6 and older browsers), and if you wanted to do clever transformation of your source data, there were ways to achieve that other than formatting the markup sent to the browser as a subset of XML

reply
jasode
5 hours ago
[-]
>Why is this a problem for HTML - and only HTML?

Your premise is not correct because you're not aware that other data formats also have parsers that accept malformed content. Examples:

- pdf files: many files with errors can be read by Adobe Acrobat. And code PDF libraries for developers often replicate this behavior so they too can also open the same invalid pdf files.

- zip files. 7-Zip and WinRAR can open some malformed zip files that don't follow the official PKZIP specification. E.g. 7-Zip has extra defensive code that looks for a bad 2-byte sequence that shouldn't be there and skips over it.

- csv files. MS Excel can read some malformed csv files.

- SMTP email headers: Mozilla Thunderbird, MS Outlook, etc can parse fields that don't exactly comply with RFC 822 -- make some guesses -- and then successfully display the email content to the user

The common theme to the above, including HTML... the Raw Content is more important than a perfectly standards-compliant file format. That's why parsers across various domains make best efforts to load the file even when it's not 100% free of syntax errors.

>Meanwhile, in any other formal language (including JS and CSS!), the standard assumption is that syntax errors are fatal,

Parsing invalid CSS is not a fatal error. Example of validating HTML/CSS in a job listings webpage at Monster.com : https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.monster.c...

It has CSS errors such as:

  Error: CSS: background-color: none is not a background-color value.  From line 276, column 212; to line 276, column 215
  Error: CSS: padding: 8x is not a padding value.
Job hunters in the real world want to see the jobs because the goal is to get a paycheck. Therefor, a web browser that didn't show the webpage just because the author mistakenly wrote CSS "none" instead "transparent" and "8x" instead of "8px" -- would be user hostile software.
reply
magicalhippo
4 hours ago
[-]
> csv files. MS Excel can read some malformed csv files.

At work we have to parse CSV files which often have mixed encoding (Latin-1 with UTF-8 in random fields on random rows), occasionally have partial lines (remainder of line just missing) and other interesting errors.

We also have to parse fixed-width flat files where fields occasionally aren't fixed-width after all, with no discernible pattern. Customer can't fix the broken proprietary system that spits this out so we have to deal with it.

And of course, XML files with encoding mismatch (because that header is just a fixed string that bears no meaning on the rest of the content, right?) or even mixed encoding. That's just par for the course.

Just some examples of how fun parsing can be.

reply
nicoburns
7 hours ago
[-]
It's mostly historical. Browsers accepted invalid HTML for 10 years, there's a lot of content authored with that assumption that's never going to be updated, so now we're stuck with it.

We could be more strict for new content, but why bother if you have to include the legacy parser anyway. And the HTML5 algorithm brings us most of the benefits (deterministic parsing) of a stricter syntax while still allowing the looseness.

reply
londons_explore
7 hours ago
[-]
> never going to be updated, so now we're stuck with it.

Try going to any 1998 web page in a modern browser... It's generally so broken so as to be unusable.

As well as every page telling me to install flash, most links are dead, most scripts don't run properly (vbscript!?), tls versions now incompatible, etc.

We shouldn't put much effort into backwards compatibility if it doesn't work in practice. The best bet to open a 1998 web page is to install IE6 in a VM, and everything works wonderfully.

reply
afavour
6 hours ago
[-]
The vast majority of pages from 1998 work fine today. VBscript was always a tiny minority of scripting. And link rot is an undeniable problem but that’s not an issue with the page itself.
reply
Kwpolska
5 hours ago
[-]
You’re unlikely to find a 1998-era Web page still running a 1998-era SSL stack. SSL was expensive (computationally and CA-cartel-ically), so basically banks and online shopping would have used SSL back then.
reply
bazoom42
7 hours ago
[-]
Syntax errors are not fatal in CSS. CSS has detailed rules for how to handle and recover from syntax errors, usually by skipping the invalid token. This is what allows introducing new syntax in a backwards-compatible manner.
reply
alwillis
1 hour ago
[-]
> Meanwhile, in any other formal language (including JS and CSS!), the standard assumption is that syntax errors are fatal,

In CSS, a syntax error isn't fatal. Most of the time, an unrecognized property causes that selector and all its properties to be ignored.

:is() and :where() support forgiving selector list [1].

Only the erroneous properties are ignored; the rest work normally.

[1]: https://drafts.csswg.org/selectors-4/#typedef-forgiving-sele...

reply
dragonwriter
4 hours ago
[-]
> What I never understood was why, for HTML specifically, syntax errors are such a fundamental unsolvable problem that it's essential that browsers accept bad content.

Because HTML is a content language, and at any given time the main purpose of the main engines using it will be to access a large array of content that is older than the newest revision of the language, and anything that creates significant incompatibilities or forces completely rewrites of large bodies of work to incorporate new features in a standard is simply not going to be implemented as specified by the major implementers (it will either not be implemented at all, or will be modified), because it is hostile what the implementations are used for.

reply
barnabee
6 hours ago
[-]
Because HTML is designed to be written by everyone, not just “engineers” and we’d rather be able to read what they have to say even if they get it wrong.
reply
halapro
3 hours ago
[-]
It's more that it's exceedingly easy to generate bad X(H)ML strings especially back when you had PHP concatenating strings as you went. Most HTML on the web is live/dynamic so there's no developer to catch syntax errors and "make build" again.
reply
hinkley
6 hours ago
[-]
I was there, Gandalf. I was there 30 years ago. I was there when the strength of men failed.

Netscape started this. NCSA was in favor of XML style rules over SGML, but Netscape embraced SGML leniency fully and several tools of that era generated web pages that only rendered properly in Netscape. So people voted with their feet and went to the panderers. If I had a dollar for every time someone told me, “well it works in Netscape” I’d be retired by now.

reply
pwdisswordfishy
6 hours ago
[-]
> It probably didn't help that XHTML did not offer any new features over tag-soup HTML syntax.

Well, this is not entirely true: XML namespaces enabled attaching arbitrary data to XHTML elements in a much more elegant, orthogonal way than the half-assed solution HTML5 ended up with (the data-* attribute set), and embedding other XML applications like XForms, SVG and MathML (though I am not sure how widely supported this was at the time; some of this was backported into HTML5 anyway, in a way that later led to CVEs). But this is rather niche.

reply
Sankozi
4 hours ago
[-]
Emitting correct XHTML was not that hard. The biggest problem was that browsers supported plugins that could corrupt whole page. If you created XHTML webpage you had to handle bug reports caused by poorly written plugins.
reply
bazoom42
9 hours ago
[-]
Why did markdown become popular when we already have html? Because markdown is much easier to write by hand in a simple text editor.

Original SGML was actually closer to markdown. It had various options to shorten and simplify the syntax, making it easy to write and edit by hand, while still having an unambiguous structure.

The verbose and explicit structure of xhtml makes it easier to process by tools, but more tedious for humans.

reply
nathankleyn
5 hours ago
[-]
Personally I think Markdown got _really_ popular not because it is easier to write but because it is easier to read.

It’s kind of a huge deal that I can give a Markdown file of plain text content to somebody non-technical and they aren’t overwhelmed by it in raw form.

HTML fails that same test.

reply
epolanski
5 hours ago
[-]
Or because it was the default in GitHub with an ad hoc renderer.
reply
stouset
5 hours ago
[-]
Markdown has been extremely popular since far before GitHub existed.
reply
thrdbndndn
3 hours ago
[-]
I'm sure Markdown was already popular, but I agree with the OP that GitHub made it orders of magnitude more popular.

Previously its popularity was somewhat similar to RST.

reply
epolanski
5 hours ago
[-]
Sure, but it became kind of the default with GitHub taking a lead position in code repository services.
reply
singingbard
4 hours ago
[-]
People had already ditched writing HTML for years before Markdown came out.

People were just using other markup languages like rST.

Other attempts had already proven HTML to be a bad language for rough documentation. Someone then just needed to write a spec that was easy to implement and Markdown was that.

reply
oneeyedpigeon
7 hours ago
[-]
Is it really that much easier to write `<br>` and know that it isn't a problem, than just write `<br />`?
reply
barnabee
6 hours ago
[-]
It’s much easier to have to remember fewer rules and for things to be ok if you get some wrong, yes.

Especially for casual users of HTML.

reply
epgui
5 hours ago
[-]
Bad reasoning.

“Always close your tags” is a simpler rule (and fewer rules, depending how you count) than “Close your tags, except possibly in situations A, B, C…”.

reply
intrasight
5 hours ago
[-]
I've been closing my tags for 30 years and I assume that I will for the rest of my days. I like that it validates as XML. Historically I used XSLT a LOT.
reply
eastbound
1 hour ago
[-]
It triggers the linters so often. I shall keep my <input> tag open.
reply
TZubiri
5 hours ago
[-]
But learning about self closing tags is an additional rule
reply
wizzwizz4
2 hours ago
[-]
<script /> is invalid HTML, and <img></img> is also invalid HTML. There's no way to avoid knowing HTML syntax.
reply
Pxtl
6 hours ago
[-]
Imho the real strength of markdown is it forces people to stick to classes instead of styling. "I want to write in red comic Sans" " I don't care, you can't".

And markdown tables are harder to write than HTML tables. However, they are generally easier to read. Unless multi line cell.

reply
jbaber
6 hours ago
[-]
I usually just write html tables, then convert to markdown via pandoc. It's a crazy world we live in.
reply
dragonwriter
4 hours ago
[-]
> I never understood why the more strict rules of XML for HTML never took off.

Because of the vast quantity of legacy HTML content, largely.

> HTML 5 was an opportunity to make a clear cut between legacy HTML and the future of HTML.

WHATWG and its living standard that W3C took various versions of and made changes to and called it HTML 5, 5.1, etc., to pretend that they were still relevant in HTML, before finally giving up on that entirely, was a direct result of the failure of XHTML and the idea of a clear cut between legacy HTML and the future of HTML. It was a direct reaction against the “clear cut” approach based on experience, not an opportunity to repeat its mistakes. (Instead of a clear break, HTML incorporated the “more strict rules of XML” via the XML serialization for HTML; for the applications where that approach offers value, it is available and supported and has an object model 100% compatible with the more common form, and they are maintained together rather than competing.)

reply
mgr86
3 hours ago
[-]
I'd argue XHTML did take off and was very widely adopted for the first 5-10 years of the century.
reply
MarsIronPI
7 hours ago
[-]
Because I want my hand-written HTML to look more like markdown-style languages. If I close those tags it adds visual noise and makes the text harder to read.

Besides, at this point technologies like tree-sitter make editor integration a moot point: once tree-sitter knows how to parse it, the editor does too.

reply
kbolino
6 hours ago
[-]
A lot of HTML tags never have a body, so it makes no sense to close them. XML has self-closing tag syntax but it wasn't always handled well by browsers.

A p or li tag, at least when used and nested properly, logically ends where either the next one begins or the enclosing block ends. Closing li also creates the opportunity for nonsensical content inside of a list but not in any list item. Of course all of these corner cases are now well specified because people did close their tags sometimes.

reply
afavour
6 hours ago
[-]
> A p or li tag, at least when used and nested properly, logically ends where either the next one begins or the enclosing block ends

While this is true I’ve never liked it.

    <p>blah<p>blah2</p>
Implies a closing </p> in the middle. But

    <p>blah<span>blah2</p>
Does not. Obviously with the knowledge of the difference between what span and p represent I understand why but in terms of pure markup it’s always left a bad taste in my mouth. I’ll always close tags whenever relevant even if it’s not necessary.
reply
kbolino
6 hours ago
[-]
This interpretation of the p element implies that it contains a paragraph. But HTML is first and foremost a document format, and one could just as logically conclude that the p element simply starts a new paragraph. Under the latter interpretation, </p> would never exist any more than </hr> or </img>.

In practice, modern HTML splits the difference with rigorous and well defined but not necessarily intuitive semantics.

reply
Pxtl
6 hours ago
[-]
> XML has self-closing tag syntax but it wasn't always handled well by browsers.

So we'll add another syntax for browsers to handle.

https://xkcd.com/927/

reply
kbolino
5 hours ago
[-]
I was going to respond that HTML was the original syntax and XML the usurper, but a comment in another thread casts some doubt on that version of events: https://news.ycombinator.com/item?id=46576844
reply
coffeefirst
6 hours ago
[-]
I would argue the stricter rules did take off, most people always close <p>, it's pretty common to see <img/> over <img>—especially from people who write a lot of React.

But.

The future of HTML will forever contain content that was first handtyped in Notepad++ in 2001 or created in Wordpress in 2008. It's the right move for the browser to stay forgiving, even if you have rules in your personal styleguide.

reply
ndiddy
4 hours ago
[-]
> I learned HTML quite late, when HTML 5 was already all the rage, and I never understood why the more strict rules of XML for HTML never took off. They seem so much saner than whatever soup of special rules and exceptions we currently have.

XHTML came out at a time when Internet Explorer, the most popular browser, was essentially frozen apart from security fixes because Microsoft knew that if the web took off as a viable application platform it would threaten Windows' dominance. XHTML 1.1 Transitional was essentially HTML 4.01 except that if it wasn't also valid XML, the spec required the browser to display a yellow "parsing error" page rather than display the content. This meant that any "working" XHTML site might not display because the page author didn't test in your browser. It also meant that any XHTML site might break at any time because a content writer used a noncompliant browser like IE 6 to write an article, or because the developers missed an edge case that causes invalid syntax.

XHTML 2.0 was a far more radical design. Because IE 6 was frozen, XHTML 2.0 was written with the expectation that no current web browser would implement it, and instead was a ground-up redesign of the web written "the right way" that would eventually entirely replace all existing web browsers. For example, forms were gone, frames were gone, and all presentational elements like <b> and <i> were gone in favor of semantic elements like <strong> and <samp> that made it possible for a page to be reasoned about automatically by a program. This required different processing from existing HTML and XHTML documents, but there was no way to differentiate between "old" and "new" documents, meaning no thought was given to adding XHTML 2.0 support to browsers that supported existing web technologies. Even by the mid-2000s, asking everyone to restart the web from scratch was obviously unrealistic compared to incrementally improving it. See here for a good overview of XHTML 2.0's failure from a web browser implementor's perspective: https://dbaron.org/log/20090707-ex-html

reply
jrm4
4 hours ago
[-]
This really does feel like a job for auto-complete -slash- Generative ai tools.
reply
Wowfunhappy
5 hours ago
[-]
Imagine if you were authoring and/or editing prose directly in html, as opposed to using some CMS. You're using your writing brain, not your coding brain. You don't want to think about code.

It's still a little annoying to put <p> before each paragraph, but not by that much. By contrast, once you start adding closing tags, you're much closer to computer code.

I'm not sure if that makes sense but it's the way I think about it.

reply
SoftTalker
4 hours ago
[-]
It's honestly no worse than Markdown, reST, or any of the other text-based "formats." It's just another format.

Any time I have to write Markdown I have to open a cheat sheet for reference. With HTML, which I have used for years, I just write it.

reply
onion2k
7 hours ago
[-]
In the case of <br/> and <img/> browsers will never use the content inside of the tag, so using a closing tag doesn't make sense. The slash makes it much clearer though, so missing it out is silly.
reply
ndiddy
6 hours ago
[-]
"Self-closing tags" are not a thing in HTML5. From the HTML standard:

> On void elements, [the trailing slash] does not mark the start tag as self-closing but instead is unnecessary and has no effect of any kind. For such void elements, it should be used only with caution — especially since, if directly preceded by an unquoted attribute value, it becomes part of the attribute value rather than being discarded by the parser.

It was mainly added to HTML5 to make it easier to convert XHTML pages to HTML5. IMO using the trailing slash in new pages is a mistake. It makes it appear as though the slash is what closes the element when in reality it does nothing and the element is self-closing because it's part of a hardcoded set of void elements. See here for more information: https://github.com/validator/validator/wiki/Markup-%C2%BB-Vo...

reply
ndriscoll
6 hours ago
[-]
It's not a mistake if you want to be able to use XML tools on your HTML. It's basically no effort to make HTML also be valid XML so you'd might as well get the additional tooling compatibility and simplicity for free. For the same reason, it's courteous toward others.
reply
Hendrikto
5 hours ago
[-]
Self-closing tags do nothing in HTML though. They are ignored. And in some cases, adding them obfuscates how browser’s will actually interpret the markup, or introduce subtle differences between HTML and JSX, for example.
reply
jakelazaroff
6 hours ago
[-]
How does the slash make it clearer? It's totally inert, so if you try to do the same thing with a non-void tag the results will not be what you expect!
reply
onion2k
6 hours ago
[-]
It indicates that the content that follows is not inside of the tag without the reader needing to remember how HTML works. Tags should have either a self-closing slash, or a closing tag.

The third way of a bare tag is where the confusion comes from.

reply
jakelazaroff
6 hours ago
[-]
It doesn't indicate that, though. If you write <div />, for example, the content that follows is inside of the tag. So the reader still needs to remember how HTML works, because the slash does nothing.
reply
jraph
6 hours ago
[-]
Contrary to <img /> or <br />, <div /> is necessarily a mistake or intentionally misleading. The unfamiliar reader should not stumble upon <div /> too often. <div /> is a bug. It's a bit like using misleading indentation in C-like programming languages. Yeah, it can happen, and is a source of bugs, but if the page is well written, the regularity of having everything closed, even if it's decorative for the spec, can help the unfamiliar reader who doesn't have all the parsing rules in mind.

Now, we can discuss whether we should optimize for the unfamiliar reader, and whether the illusion of actual meaning the trailing slash in HTML5 can be harmful.

I would note that exactly like trailing slashes, indentation doesn't mean anything for the parser in C-like languages and can be written misleadingly, yet we do systematically use it, even when no unfamiliar reader is expected.

At this point, writing a slash or not and closing all the tags is a coding style discussion.

Now, maybe someone writing almost-XHTML (closing all tags, putting trailing slashes, quoting all the attributes) should go all the way and write actual XHTML with the actual XHTML content type and benefit from the strict parser catching potential errors that can backfire and that nobody would have noticed with the HTML 5 parser.

reply
vbezhenar
11 hours ago
[-]
> why would you ever want to not close tags?

Because browsers close some tags automatically. And if your closing tag is wrong, it'll generate empty element instead of being ignored. Without even emitting warning in developer console. So by closing tags you're risking introducing very subtle DOM bugs.

If you want to close tags, make sure that your building or testing pipeline ensures strict validation of produced HTML.

reply
notepad0x90
20 minutes ago
[-]
<p>some sentence here <img src="img.jpeg"/> <p> some other sentence.

In that example, the image could be part of the first paragraph, as it is there, or if i moved the second <p> before the <img> it would be part of the second. but if I want neither, do I not have to close the first paragraph?

Here is a demo of what i mean on this random html paste site: https://htmlbin.online/closetagdemo

I don't know what "not required" means, but it makes a difference with <p> at least in my opinion. I think the author meant that if the succeeding element is of the same type, you don't need to close the previous one.

But even then, this is not a good feature, browsers aren't the only things processing html content, any number of tooling, or even human readers can get confused.

reply
delaminator
2 days ago
[-]
Go back a bit further for why.

Netscape Navigator did, in fact, reject invalid HTML. Then along came Internet Explorer and chose “render invalid HTML dwim” as a strategy. People, my young naive self included, moaned about NN being too strict. NN eventually switched to the tag soup approach. XHTML 1.0 arrived in 2000, attempting to reform HTML by recasting it as an XML application. The idea was to impose XML’s strict parsing rules: well-formed documents only, close all your tags, lowercase element names, quote all attributes, and if the document is malformed, the parser must stop and display an error rather than guess. XHTML was abandoned in 2009. When HTML5 was being drafted in 2004-onwards, the WHATWG actually had to formally specify how browsers should handle malformed markup, essentially codifying IE’s error-recovery heuristics as the standard.

reply
bazoom42
12 hours ago
[-]
But not closing <p> etc has always been valid HTML. Back from SGML it was possible for closing tags to be optional (depending on the DTD), and Netscape supported this from the beginning.

Leaving out closing tags is possible when the parsing is unambigous. E.g <p>foo<p>bar is unambiguous becuse p elements does not nest, so they close automatically by the next p.

The question about invalid HTML is a sepearate issue. E.g you can’t nest a p inside an i according to the spec, so how does a browser render that? Or lexical error like illegal characters in a non-quoted attribute value.

This is where it gets tricky. Render anyway, skip the invalid html, or stop rendering with an error message? HTML did not specify what to do with invalid input, so either is legal. Browsers choose to go with the “render anyway” approach, but this lead to different outputs in different browsers, since it wasn’t agreed upon how to render invald html.

The difference between Netscape and IE was that Netscape in more cases would skip rendering invalid HTML, where IE would always render the content.

reply
Sniffnoy
13 hours ago
[-]
The article itself falsifies this explanation; IE wasn't released until August 1995. The HTML draft specs published prior to this already specified that these tags didn't need closing; these simply weren't invalid HTML in the first place.

The oldest public HTML documentation there is, from 1991, demonstrates that <li>, <dt>, and <dd> tags don't need to be closed! And the oldest HTML DTD, from 1992, explicitly specifies that these, as well as <p>, don't need closing. Remember, HTML is derived from SGML, not XML; and SGML, unlike XML, allows for the possibility of tags with optional close. The attempt to make HTML more XML-like didn't come until later.

reply
ezequiel-garzon
12 hours ago
[-]
Optinal tags have always been allowed in HTML, for the simple if debatable reason (hence xhtml) that some humans still author documents by hand, knowingly skip md et al _and_ want to write as few characters as possible (I do!).

This is clear in Tim Berners-Lee's seminal, pre-Netscape "HTML Tags" document [0], through HTML 4 [4] and (as you point out) through the current living standard [5].

[0] https://www.w3.org/History/19921103-hypertext/hypertext/WWW/...

[4] https://www.w3.org/TR/html401/intro/sgmltut.html#h-3.2.1

[5] https://html.spec.whatwg.org/multipage/syntax.html#optional-...

reply
pornel
12 hours ago
[-]
NN did not reject invalid HTML. It could not incrementally render tables, while IE could. That's all.

Because table layout was common, a missing </table> was a common error that resulted in a blank page in NN. That was a completely unintentional bug.

Optional closing tags were inherited from SGML, and were always part of HTML. They're not even an error.

reply
neilv
11 hours ago
[-]
I didn't know that Navigator was ever strict, and bit funny story about when I complained that they hadn't been strict...

Around 2000, I was meeting with Tim Berners-Lee, and I mentioned I'd been writing a bunch of Web utility code. He wanted to see, so I handed him some printed API docs I had with me. (He talked and read fast.)

Then I realized he was reading the editorializing in my permissive parser docs, about how browser vendors should've put a big error/warning message on the window for invalid HTML.

Which suddenly felt presumptuous of me, to be having opinions about Web standards, right in front of Tim Berners-Lee at the time.

(My thinking with the prominent warning message that every visitor would see, in mid/late-'90s, was that it would've been compelling social pressure at the time. It would imply that this gold rush dotcom or aspiring developer wasn't good at Web. Everyone was getting money in the belief that they knew anything at all about Web, with little way to evaluate how much they knew.)

reply
hinkley
6 hours ago
[-]
Former NCSA employee here. The fuck they did. Netscape caught us out time and again for accepting SGML garbage that we didn’t handle properly. It’s a big part of why Netscape won that round of the browser wars. Such recovery then wound up in tools that generated web pages for you and it was all over but the crying. JavaScript was just the last straw. Which I tried to talk them into adopting but got no traction.
reply
cvcount
12 hours ago
[-]
I have bad memories of Netscape 4 and IE4 (I think those were the versions) which both allowed invalid HTML but had different rules for doing it. Accidentally missed off a closing table tag once, and one browser displayed the remainder of the page, but the other didn't.
reply
ZiiS
12 hours ago
[-]
You are also not required to indent code (in most languages); please do if you want me to read it though.
reply
dashzebra
12 hours ago
[-]
You can also indent with spaces and tabs at the same time, who's judging?
reply
Quarrel
11 hours ago
[-]
Not in python, which is how I always discover someone is using tabs ..
reply
jeroenhd
6 hours ago
[-]
As long as you stay consistent with the whitespace count line by line, you can!
reply
danaris
12 hours ago
[-]
You monster.
reply
jpc0
11 hours ago
[-]
Golang would like a word...
reply
hinkley
6 hours ago
[-]
I would like Python a lot better if the tab character had been marked as a syntax error. Would have solved a lot of bullshit.
reply
vbezhenar
12 hours ago
[-]
Closing optional HTML tags just adds more ambiguity. How many HTMLParagraphElements here, what do you think?

    <p>
      text1
      <p>
        text2
      </p>
    </p>
reply
hnlmorg
12 hours ago
[-]
2. And there’s no ambiguity there, just invalid HTML because paragraphs aren’t nestable.
reply
kzrdude
12 hours ago
[-]
It may look nested but the first p is actually closed when the second p starts, according to https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/...
reply
jchw
12 hours ago
[-]
Wouldn't this still result in just two paragraph elements? Yes, the first gets auto-closed, but I don't see how a third paragraph could emerge out of this. Surely that closing tag should just get discarded as invalid.

edit: Indeed, it creates three: the </p> seems to create an empty paragraph tag. Not the first time I've been surprised by tag soup rules.

reply
hnlmorg
11 hours ago
[-]
Hence why I said “2” ;)
reply
vbezhenar
11 hours ago
[-]
Browser will parse that as three HTMLParagraphElements. You may think that's invalid HTML, but browser will parse it and won't indicate any kind of error.
reply
hnlmorg
11 hours ago
[-]
> Browser will parse that as three HTMLParagraphElements

Why?

> You may think that's invalid HTML, but browser will parse it and won't indicate any kind of error.

It isn’t an opinion, it literally is invalid HTML.

What you’re responding to is an assumption that I was suggesting browsers couldn’t render that. Which isn’t what I claimed at all. I know full well that browsers will gracefully handle incorrect HTML, but that doesn’t mean that the source is magically compliant with the HTML specification.

reply
LorenzA
4 minutes ago
[-]
>Why?

Because the second open p-tag closes the first p-tag and then the last closing p has no matching starting p-tag and creates one thus resulting in 3 p-elements.

> It isn’t an opinion, it literally is invalid HTML.

the only "invalid" part is the last closing p.

reply
vbezhenar
11 hours ago
[-]
> Why?

I don't know why. Try it out. That's the way browsers are coded.

> It isn’t an opinion, it literally is invalid HTML.

It matters not. You're writing HTML for browser to consume, not for validator to accept. And most of webpages are invalid HTML. This very HN page contains 412 errors and warnings according to W3C validator, so the whole point of HTML validness is moot.

reply
hnlmorg
11 hours ago
[-]
> I don't know why. Try it out. That's the way browsers are coded.

I’m not saying you’re wrong, but I’d need more than that to be convinced. Sorry.

> It matters not. You're writing HTML for browser to consume, not for validator to accept.

It matters because you’re arguing a strawman argument.

We weren’t discussing what a browser can render. We were discussing the source code.

So your comment wasn’t a rebuttal of mine. It was a related tangent or addition.

reply
vbezhenar
11 hours ago
[-]
> I’m not saying you’re wrong, but I’d need more than that to be convinced. Sorry.

So basically my point is:

1. You can avoid closing some tags, letting browser to close tags for you. It won't do any harm.

2. You can choose to explicitly close all tags. It won't do anything for valid HTML, but it'll introduce subtle and hard to find DOM bugs by adding empty elements.

So you're trying to improve HTML source readability by risking to introduce subtle bugs.

If you want to do that, I'd recommend to implement HTML validation for build or test pipeline at least.

Another alternative is to use HTML comments to close tags, as this closing tag is supposed to be documentation-only and won't be used by browser in a proper code.

reply
hnlmorg
11 hours ago
[-]
I get your point, but again, that’s not relevant to the point I was making.

You posted a terse comment with some HTML. I responded specifically about that comment and HTML. And you’re now elaborating on things as a rebuttal to my comment despite the fact that wasn’t the original scope of my comment.

Another example of that is how you’ve quoted my reply to the 2 vs 3 elements, and then answered a completely different question (one I didn’t even ask).

I don’t think you’re being intentionally obtuse but it’s still a very disingenuous way to handle a discussion.

reply
allreduce
4 hours ago
[-]
> You're writing HTML for browser to consume, not for validator to accept.

I'm not a web programmer, but shouldn't one program against the specified interface instead of some edge case behavior of an implementation?

reply
psychoslave
11 hours ago
[-]
At the end of the day, browsers have to handle most of the invalid atrocities thrown at it.

It doesn't make the code valid according to the specifications.

reply
vbezhenar
11 hours ago
[-]
My point is that by closing optional tags you can introduce subtle bugs into your layout that might take some time to find and browser won't be of any help. You write closing tag, browser will implicitly add starting tag. It's better to memorise which tags are optional and do not close them at all.
reply
hnlmorg
11 hours ago
[-]
You can also introduce subtle bugs by not closing them. Or forgetting which tags can be closed and thus leaving the wrong ones dangling.

So I think your argument here is tough to take at face value. It feels a lot more like you’re arguing personal preference as fact.

reply
psychoslave
6 hours ago
[-]
Precisely, it's an added burden to remember and what might be skipped. The less many exception, the better.

Though if a linter is formatting the whole codebase on its own in an homogeneous way, and someone else will deal with the added parsing complexity, that might feel okayish also to me.

Generally speaking, the less clutter the better. A bit like with a js codebase which is semicolon free where possible.

For pleasant experience of read and write, html in a simple text editor is very low quality. Pug for example is bringing far less clutter, though mandatory space indentation could be avoided with some alternative syntactic choices.

reply
urbandw311er
11 hours ago
[-]
Excellent catch
reply
have_faith
12 hours ago
[-]
Why would you nest paragraph tags?
reply
Hendrikto
5 hours ago
[-]
They are not nested, according to HTML5 parsing rules. You get 3 (yes, three) sibling paragraphs, including an empty one.

There being nesting is just implied by the closing tags and indentation. But it is not actually there. I think this is the point of the example: Adding the closing tags just confuses the reader, by implying nesting that is not actually there, and even introduces a third empty paragraph. It might be better left out entirely.

reply
b2ccb2
12 hours ago
[-]
That is invalid syntax. Only phrasing content is allowed the p element (https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Con...)
reply
jeroenhd
6 hours ago
[-]
The second <p> is not inside of the first. The first <p> closes when the second <p> is encountered.

The syntax is invalid, but that's because the final </p> has no opening <p> that it can close.

reply
psychoslave
11 hours ago
[-]
This is invalid html, p tag can be nested in a p tag.
reply
Hendrikto
5 hours ago
[-]
Even though it arguably should be, according to HTML5 parsing rules, this is not invalid. It is just interpreted differently from what most people would probably expect.

I think this is the point of the example, afaiui: The closing tags don’t clarify anything, quite the contrary, actually. They serve only to confuse the reader.

reply
carlosjobim
6 hours ago
[-]
HTML is more content than programming logic, so it shouldn't be indented.
reply
dhosek
4 hours ago
[-]
The “loose” standards of HTML led to some really awful things happening in the early web. I remember seeing, e.g.,

     <large><li></large> item text
to get a bigger bullet on a list item which worked fine in Netscape but broke other browsers (and since I was on OS/2 at the time, it was an issue for me).

Really, in 2025 people should just write XHTML and better yet, shouldn’t be generating HTML by hand at all except for borderline cases not handled by their tools.

reply
webstrand
4 hours ago
[-]
Unfortunately XHTML5 doesn't exist and if you try to force the issue, you have to re-declare all of the non-numeric HTML entities in your own DTD (I abandoned the idea here). I'd love to use XHTML, its just not viable anymore.

As for generating all HTML, that's simply not possible given the current state (of open-source at least) WYSIWYG HTML editors.

reply
lcnmrn
3 hours ago
[-]
I wish HTML 6 will actually be XHTML 6.
reply
EmilStenstrom
4 hours ago
[-]
To see the actual errors, just paste your HTML here and see: https://emilstenstrom.github.io/justhtml/playground/ - any parsing errors show up below the input box.

Some tags do require ending tags, others do not. Personally I find it hard to remember which ones, so I just close things out of caution. That way you’re always spec-correct.

reply
didip
7 hours ago
[-]
Early Google did not close their tags, I think it was for the sake of payload size?

That said, your linter is going to drive you crazy if you don't close tags, no?

reply
dizzy9
6 hours ago
[-]
How the mighty have fallen. A search on YouTube now pulls in 2.14 MB of HTML alone.
reply
ratsbane
6 hours ago
[-]
This is more of a problem with linters.
reply
jihadjihad
3 hours ago
[-]
I didn’t have any rigorous training or anything, but my understanding since learning HTML way back in high school was, like the author mentions in TFA, tags like <br> and <p> can simply be used “as-is” as markup and don’t need the concept of being closed.

I write virtually zero HTML anymore, but the one time this sort of thing comes up is in writing PR descriptions in GitHub using Markdown. Sometimes I want to add a <br> or two for space. I guess I’ve never stopped to notice that I never close those tags after adding them, or wondered why in my head it makes sense not to!

reply
hk1337
1 hour ago
[-]
You’re not really required to with anything in HTML or to even use HTML, you could do everything plain text if you wanted
reply
1vuio0pswjnm7
4 hours ago
[-]
I use this daily with local HTML files, specifically not closing <li> tags

For example, I generate numbered lists of URLs something like

   <li><a href=http://example.com>http://example.com</a>
This is for text-only browser

If I am viewing in graphical browser I wrap the lists in <pre> tags

I don't think I've ever closed <br> tags

reply
themafia
12 hours ago
[-]
Yea but it feels gross when I don't.
reply
patrickmay
7 hours ago
[-]
You just confessed to having taste.
reply
renegade-otter
12 hours ago
[-]
Just because you can, doesn't mean you should.
reply
timonoko
12 hours ago
[-]
<p> was the only thing I knew when I constructed Finland's First Ever WEB-page in 1992.

Correction: there was also the issue of Ä and Ö. Those were &AUML; and &OUML; I think.

https://timonoko.github.io/alaska/index.htm

reply
timonoko
9 hours ago
[-]
On 640x480 VGA-display this page looks quite alright.
reply
thedelanyo
4 hours ago
[-]
I cannot fathom writing <p> without</p> to wrap a text.
reply
downsplat
2 hours ago
[-]
You do you in terms of taste, but the article explains very clearly that there's nothing wrong about not closing them, as they are reliably auto-closed by a well-defined standard.
reply
BiraIgnacio
2 hours ago
[-]
I'd think handling these cases would be nightmare for html parsers.
reply
robust-cactus
7 hours ago
[-]
How does all this interact with html minification? IIRC you can't nest p tags but you can nest li, so does browser just make assumptions about your intent. Is it not better to state your intent as clearly as possible if not for a browser, then for the next developer?

Payload size is a moot point given gzip.

reply
jerf
6 hours ago
[-]
Perhaps the most distinguishing characteristic of HTML5 is that it specifies exactly what to do with tag soup. The rules are worth a glance at some time, just to see how rather absurdly complicated they are to do the job of picking up the pieces of who knows how many terabytes and petabytes of garbage HTML were generated before they were codified in an attempt to remain backwards compatible with the various browsers prior to that. And then you'll understand why I'm not going to even begin to attempt to answer your question about how browsers handle various tag combinations. Instead my point is only that, with HTML5, there is in fact a very concrete answer that is no longer up to the browsers trying to each individually spackle over the various and sundry gaps in the standards.

But honestly no answer to "what does the browser do with this sort of thing" fits into an HN comment anymore. I'm glad there's a standard, but there's a better branch of the multiverse where the specification of what to do with bad HTML was written from the beginning and is much, much simpler.

reply
jakelazaroff
7 hours ago
[-]
You cannot nest <li>. An <li> may only be a child of <ol>, <ul> or <menu>.

https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/...

reply
seydor
12 hours ago
[-]
Yeah but it's better for your mental sanity. It's not just a habit, the closure reduces the mental load and helps to keep track of structure in the messy world of html documents. So it is actually more efficient
reply
QuantumNomad_
12 hours ago
[-]
It depends completely on how nested your HTML tags are.

I hand write my HTML sometimes, and in those cases it’s often very basic documents consisting of maybe an outer container div, a header and a nav with a ul of li for the navigation items and then an inner container div and maybe an article element, and then the contents are mostly p and figure elements and various level headings.

In this case, there is no mental overhead of omitting closing li and closing p at the end of the line, and I omit them because I am allowed to and it’s still readable and fine.

reply
kstrauser
5 hours ago
[-]
I tried using XHTML when we were told, loudly and repeatedly, that it was the inevitable future. Thank god it wasn’t.

You should close your tags. It’s good hygiene. It helps IDEs help you. But. Trust me, you do not want the browser enforcing it at runtime, lest your idea of fun is end users getting helpful error messages like an otherwise blank screen saying “Invalid syntax”.

For fun, imagine that various browsers are not 100.00% compatible (“Inconceivable!”), so that it wasn’t possible to write HTML that every browser agreed was completely valid. Now it’s guaranteed that some of your users will get the error page, even when you’re sure your page is valid.

Conceptually, XHTML and its analogs are better. In practice, they’re much, much worse.

reply
nh43215rgb
12 hours ago
[-]
Please just close them though.
reply
BigTTYGothGF
6 hours ago
[-]
My experience with parsing html gathered from the wild is you're pretty much not required to do anything. "Go wild" and "have fun" seem to be the mottoes.
reply
lasgawe
4 hours ago
[-]
I never knew that. I don't know why. I've never seen this mentioned in a book, tutorial, or anything.
reply
nine_k
12 hours ago
[-]
You don't need to close these tags. But if you value your sanity more than saving a few bytes, you as well may close them, it's not an error.
reply
dangoodmanUT
7 hours ago
[-]
Considering I can’t scroll down on ios safari, maybe you should…
reply
jeroenhd
6 hours ago
[-]
Works fine on every browser I've thrown at it. Even Gnome Web (WebKit) allows scrolling just fine. Sounds like a Safari bug? Maybe a content blocker interfering with the page?
reply
senfiaj
3 hours ago
[-]
Maybe you are not required to close, browsers are ridiculously tolerant to html mistakes. But do you think it would be easy to maintain that HTML file and not accidentally include something in that unclosed tag? I often format with indentation in order to work with the file comfortably.

Also it annoys me when people are still closing tags with '/>'.

reply
downsplat
2 hours ago
[-]
Did you read the article? An unclosed <p> is not a mistake that the browser is tolerating, it's 100% well-defined html5 according to spec. If your tooling can't handle the language as defined, maybe the problem is with the tooling.
reply
strogonoff
11 hours ago
[-]
There are ways for not closing HTML tags to backfire in some scenarios.

Some rules of thumb, perhaps:

— Do not omit if it is a template and another piece of HTML is included in or after this tag. (The key fact, as always, is that we all make errors sometimes—and omitting a closing tag can make an otherwise small markup error turn your tree into an unrecognisable mess.)

— Remember, the goal in the first place is readability and improved SNR. Use it only if you already respect legibility in other ways, especially the lower-hanging fruit like consistent use of indentation.

— Do not omit if takes more than a split-second to get it. (Going off the HTML spec, as an example, you could have <a> and <p> as siblings in one container, and in that case if you don’t close some <p> it may be non-obvious if an <a> is phrasing or flow content.)

The last thing you want is to require the reader of your code to be more of an HTML parser than they already have to be.

For me personally this makes omitting closing tags OK only in simpler hand-coded cases with a lot of repetition, like tables, lists, definition lists (often forgotten), and obviously void elements.

reply
gregoriol
12 hours ago
[-]
I get why you may not close <img> or <br> since they don't contain anything inside, but <p> and <li> should be closed to indicate the end of the content, otherwise it's shows you are mentally lazy and relying on some magic to do the work and guess what you wanted
reply
QuantumNomad_
12 hours ago
[-]
To each their own. In simple lists for navigation menus I always omit closing li. There is no ambiguity on what I am intending even with those closing li omitted in such simple cases:

  <nav id=main-nav>
  <ul>
  <li><a href="/">Home</a>
  <li><a href="/hamburgers/">Hamburgers</a>
  <li><a href="/sausages/">Sausages</a>
  </ul>
  </nav>
reply
jeroenhd
6 hours ago
[-]
<p> indicates a new paragraph. <li> indicates a new list item. Unless otherwise specified, the existing paragraph/list item continues. There's nothing magic about any of this, it's part of the HTML spec.

Laziness doesn't play a role. This isn't XML where you need to repeat yourself over and over again or abusing a bug in the rendering logic; it's following the definitions markdown language you're writing content in.

If you're not too familiar with the HTML language then it's always a safe bet to close your tags, of course.

reply
danaris
12 hours ago
[-]
The personal judgement isn't really helpful here?

If you don't close your <p> and <li> tags, you risk accidentally having content in the wrong place.

It's something to avoid because it can have bad consequences, not because it (somehow?) makes you a bad person.

reply
blauditore
11 hours ago
[-]
I know some (or even the official?) JavaDoc style guidelines require <p> woithout closing counterparts. But to me this feels the same as omitting semicolins in JS -yes, xou can get away with it, but it's bad style in my opinion.
reply
layer8
5 hours ago
[-]
In the context of javadoc, you can think of <p> as a paragraph break, just like <br> is a line break.
reply
xg15
7 hours ago
[-]
Whether you can or can't omit a closing element is one thing, but it seems like a useful thing to be able to quickly determine if some content is inside or outside a tag, so why complicate things?

(This is especially relevant with "void" tags. E.g. if someone wrote "<img> hello </img>" then the "hello" is not contained in the tag. You could use the self closing syntax to make this more obvious -- Edit: That's bad advice, see below.)

reply
jakelazaroff
6 hours ago
[-]
The inert self closing syntax is misleading, though, because if you use it for a non-void element then whatever follows will be contained within the tag.

e.g. how do you think a browser will interpret this markup?

    <div />
    <img />
A lot of people think it ends up like this (especially because JSX works this way):

    <div></div>
    <img>
but it's actually equal to this:

    <div>
        <img>
    </div>
reply
xg15
6 hours ago
[-]
Ah, that's true. I think the WHATWG discouraged the syntax, so this might be why.
reply
ricardobeat
6 hours ago
[-]
This is really easy to detect though, unlike arbitrary rules on what belongs on the inside of an unclosed tag.
reply
oneeyedpigeon
7 hours ago
[-]
I absolutely agree. Also, if you want to parse HTML as XML, it's a lot more reliable having it in a known 'good' format to begin with.
reply
mathgeek
7 hours ago
[-]
This is where I always end up as well. Just because you can do something doesn’t mean you should or shouldn’t.
reply
osxman
13 hours ago
[-]
It would be nice though, to close 'm ... Makes it more readable and less prone to mistakes.
reply
bmacho
12 hours ago
[-]
Article actually argues/states that a lot of the times not closing elements is more readable. It mentions tables without a concrete example, but I think e.g.

  <table>
    <tr> <td> A1 <td> B1 <td> C1
    <tr> <td> A2 <td> B2 <td> C2
    <tr> <td> A3 <td> B3 <td> C3
  </table>
is valid and reads better than if the row and data elements were closed (and on separate rows because it would be too much noise otherwise) (of course the whitespaces are different, if they matter for some reason). For a 3x3 table 5 lines vs ~15 lines.
reply
hnlmorg
12 hours ago
[-]
I don’t think tables are human readable in any machine readable format, not even markdown.

The problem is when you have long cells that you’d normally word wrap inside the cell, everything else ends up misaligned in your markup language. Or when you need to add styling to text in a cell, suddenly it’s unreadable again. Or when there’s more than a small few number of columns thus causing each row to word wrap inside your IDE, etc

I think it makes far more sense to just acknowledge that tables are going to ugly, compose them elsewhere, and then export them to your markup language following that language’s specification strictly.

reply
s_ting765
5 hours ago
[-]
Same with <svg> but Firefox's XML parser will not greenlight you.
reply
MORPHOICES
12 hours ago
[-]
The HTML Specification (spec) states it is possible to omit closing tags for certain elements when writing HTML documents. ~

In fact, most web browsers now automatically insert these closing tags for the user.

This feature has been around for many years now.

However, I have found that many organizations still require that the closing tags be included explicitly.

I am curious how other organizations determine when to use the "the spec allows it" as a reason to not include the closing tags.

What point do developers cross from merely allowing this to being considered a technical debt?

Have you ever utilized the feature of the specification that caused you a problem later?

reply
chaz6
10 hours ago
[-]
If I enter the following:-

    <p><p></p>
Should the second <p> be nested or not?
reply
bazoom42
10 hours ago
[-]
No. P elements does not nest, so this is parsed as: <p></p><p></p>
reply
nubinetwork
11 hours ago
[-]
> Browsers do not treat missing optional end tags as errors that need to be recovered from

Just because it worked on the one browser you tested it on, doesn't mean it's always worked that way, or that it will always work that way in the future...

Every browser treats html/etc differently... I've run into css issues before on Chrome for android, because I was writing using Chrome for desktop as a reference.

You'd think they should be the same because they come from the same heritage, but no...

reply
JimDabell
7 hours ago
[-]
> Just because it worked on the one browser you tested it on, doesn't mean it's always worked that way, or that it will always work that way in the future...

All browsers have worked this way for decades. It’s standard HTML that has been in widespread use since the beginning of the web. The further back you go, the more normal it was to write HTML in this style. You can see in this specification from 1992 that <p> and <li> don’t have closing tags at all:

https://info.cern.ch/hypertext/WWW/MarkUp/Tags.html

Maybe there were obscure browsers that had bugs relating to this back in the mid 90s, but I don’t recall any from the late 90s onwards. Can you name a browser released this millennium that doesn’t understand optional closing tags?

reply
thrill
6 hours ago
[-]
You are if I’m doing your code review.
reply
avidphantasm
6 hours ago
[-]
…but civilized people do close them.
reply
weinzierl
12 hours ago
[-]
If I remember correctly Google's front page did this in the early days to save a few bytes.
reply
reddalo
12 hours ago
[-]
You're technically right, it seems like they had one single unclosed <p> right at the end of the page, for the copyright footer: https://web.archive.org/web/20010510221642/http://www.google...

Literally saving four bytes.

reply
Robdel12
5 hours ago
[-]
Please do, though :)
reply
6510
9 hours ago
[-]
I always thought this was funny. Practical but not the usual open/close order.

   aaaaa<b>aaaa<i>aaaaa</b>aaaa</i>aaaaa
I just tried this!

   <table>
   <tr><td>aaaaa<td>bbb
   <tr><td>ccccccccccc<td>dddddddddd
   <tr><td>eeeeeeeeeeeeeeeee
   </table>
Which works and is much cleaner than the usual table tag soup. It makes sense as on their own <td> and <tr> tags have no meaning.
reply
bell-cot
12 hours ago
[-]
Also true: You are not required to bathe IRL.

(But it might be better if you make a habit of doing so.)

reply
card_zero
12 hours ago
[-]
This is ridiculous. You're genuinely applying social pressure to close tags. I remember when this began, drove me nuts.
reply
bell-cot
11 hours ago
[-]
An anonymous account on HN is applying social pressure?

Or am I pointing out that closing tags is a human social issue, with aspects ranging from practical & reasonable, to ridiculous & widely exploited?

reply
imiric
12 hours ago
[-]
The author has a point, but I object to this mischaracterization:

> XHTML, being based on XML as opposed to SGML, is notorious for being author-unfriendly due to its strictness

This strictness is a moot point. Most editors will autocomplete the closing tag for you, so it's hardly "unfriendly". Besides, if anything, closing tags are reader-friendly (which includes the author), since they make it clear when an element ends. In languages that don't have this, authors often add a comment like `// end of ...` to clarify this. The article author even acknowledges this in some of their examples ("explicit end tags added for clarity").

But there were other potential benefits of XHTML that never came to pass. A strict markup language would make documents easier to parse, and we wouldn't have ended up with the insanity of parsing modern HTML, which became standardized. This, in turn, would have made it easier to expand the language, and integrate different processors into the pipeline. Technologies like XSLT would have been adopted and improved, and perhaps we would have already had proper HTML modules, instead of the half-baked Web Components we have today. All because browser authors were reluctant to force website authors to fix their broken markup. It was a terrible tradeoff, if you ask me.

So, sure, feel free to not close HTML tags if you prefer not to, and to "educate" everyone that they shouldn't either. Just keep it away from any codebases I maintain, thank you very much.

To be fair, I don't mind not closing empty elements, such as `<img>` or `<br>`. But not closing `<p>` or `<div>` is hostile behavior, for no actual gain.

reply
recursive
12 hours ago
[-]
Img and br are not allowed to be closed.
reply
swiftcoder
12 hours ago
[-]
Worse, due to the aforementioned permissive error handling in HTML parsers, a closing </br> tag will end up inserting a second line break
reply
hnlmorg
12 hours ago
[-]
You close them in the same tag:

    <br/>
reply
pornel
11 hours ago
[-]
This syntax is ignored in HTML. The / is thrown away and has no effect.

This non-closing talisman means that <div/> or <script/> are not closed, and will mess up nesting of elements.

reply
hnlmorg
11 hours ago
[-]
In HTML, yes. But I thought the OP was talking about XHTML?
reply
imiric
12 hours ago
[-]
Wrong.[1]

> if the element is one of the void elements, or if the element is a foreign element, then there may be a single U+002F SOLIDUS character (/)

If you're going to be pedantic, at least be correct about it.

[1]: https://html.spec.whatwg.org/multipage/syntax.html#start-tag...

reply
eddyg
11 hours ago
[-]
You left out the rest of the spec:

> On void elements, it does not mark the start tag as self-closing but instead is unnecessary and has no effect of any kind. For such void elements, it should be used only with caution — especially since, if directly preceded by an unquoted attribute value, it becomes part of the attribute value rather than being discarded by the parser.

(The void elements are listed here: https://developer.mozilla.org/en-US/docs/Glossary/Void_eleme... )

reply
imiric
11 hours ago
[-]
All of that is a far cry from elements not being allowed to be closed. Please point to where the spec mentions that. MDN is not the spec.
reply
swiftcoder
12 hours ago
[-]
There can't however be a separate closing tag, which is a reasonable interpretation of the post you are replying to
reply
Finnucane
7 hours ago
[-]
For ebook production, you need to use xhtml, the epub standard is defined that way. And it is indeed useful to be able to treat them as xml files and use xslt and xquery, etc. with them.
reply
7bit
12 hours ago
[-]
> "Did you forget to close your p tags or is that on purpose?" > [...] > These are all adapted from real comments;

If that's a comment you get, write better code. It does not matter to me whether closing p-tags is mandatory or optional. If you don't do it, I don't want you working on the same code base as me.

This kind of knowledge makes for fun blog posts, but if people direct these kind of comments to me. You're obviously using your knowledge to just patronize and lecture people.

reply
runarberg
12 hours ago
[-]
Needs a (2017) in the title.

This may have been relevant 9 years ago, but today, just pick and auto-formatter like prettierjs and have it close these tags for you.

reply
idoubtit
11 hours ago
[-]
This a very verbose and confuse article. Mixing P/LI and IMG/BR is wrong. I think the situation could be explained with two points:

1. The autoclose syntax does not exist in HTML5, and a trailing slash after a tag is always ignored. It's therefore recommended to avoid this syntax. I.e write <br> instead of <br />. For details and a list of void elements, see https://developer.mozilla.org/en-US/docs/Glossary/Void_eleme...

2. It's not mandatory to close tags when the parser can guess where they end. E.g. a paragraph cannot contain any line-block, so <p>a<div>b</div> is the same as <p>a</p><div>b</div>. It depends on the context, but putting an explicit end tag is usually less error-prone.

reply
vbezhenar
11 hours ago
[-]
Putting an explicit end tag is more error-prone. It won't do anything for valid HTML but it'll add empty tag for invalid HTML. If you want to improve human readability, put end tag enclosed in HTML comment. At least it won't add empty elements.
reply