Are you an author writing HTML?
Just so we’re clear: Not XHTML. HTML. Without the X.
If you are, repeat after me, because apparently this bears repeating (after the title):
You are not required to close your
↫ Daniel Tan<p>,<li>,<img>, or<br>tags in HTML.
Back when I still had to write OSNews’ stories in plain HTML – yes, that’s what we did for a very long time – I always properly closed my tags. I did so because I thought you had to, but also because I think it looks nicer, adds a ton of clarity, and makes it easier to go back later and make any possible changes or fix errors. It definitely added to the workload, which was especially annoying when dealing with really long, detailed articles, but the end result was worth it.
I haven’t had to write in plain HTML for ages now, since OSNews switched to WordPress and thus uses a proper WYSIWYG editor, so I haven’t thought about closing HTML tags in a long time – until I stumbled upon this article. I vaguely remember I would “fix” other people’s HTML in our backend by adding closing tags, and now I feel a little bit silly for doing so since apparently it wasn’t technically necessary at all. Luckily, it’s also not wrong to close your tags, and I stick by my readability arguments.
Sometimes it’s easy to forget just how old HTML has become, and how mangled it’s become over the years.

I’m probably an outlier among devs but I always close my `p` and `li` tags but never `img` or `br`. My reasoning is that p and li tags contain content, so it makes sense to specify where the content ends via a closing tag, whereas img and br tags don’t contain content, so they don’t need a closing tag.
emmzee,
Same.
I would agree with the auther on “void elements” that contain no content, but otherwise closing tags should be present to make it clear where that tag ends. The author talking about not closing TR TD because the browser will fix it is not a satisfying reason to leave them off IMHO. The author specifically does not like us saying the browser “fixes” it, but it is kind of what the browser ends up doing internally. It has to know where the sections end for internal representation.
If you input this html and view the debugger tools, the browser’s representation has those closing tags present. The browsers are following the practice of being liberal about the input you accept but being strict output the output you produce, which is considered a good practice in CS.
If someone wants to omit closing tags because the browsers accept it that way, I guess that’s their prerogative. I looked at the HTML behind the author’s website to see if anything stood out. I didn’t not see any examples of unclosed li or even p tags, so despite the author saying they don’t matter, the author’s website still uses closing tags.
I did notice some inconsistency in the meta and link tags though…
It doesn’t really matter because elements don’t contain content, but it’s kind of funny to see both styles used on one page.
Alfman,
This was a larger discussion during the release of HTML 4.0 and XHTML.
In XML based XHTML, you have to close your tags. (In addition to strict lower case requirements and so on)
This included leaf nodes like image or line breaks. But there was a shortcut, you could just end the tag with a / like [ img / ] (@Thom still no TT or PRE in here)
For SGML based HTML 4.0 the spec explicitly allows skipping those, and also adds implicit closing tags between repeated items like paragraphs or list elements. And did not like self closing tags.
And HTML5 combined the two. You can now use those self closing tags in HTML as well.
But I get the call for disciplined closing of all. It is nice to have.
Unfortunately the W3C HTML5 validator doesn’t like trailing slashes:
Parodper,
You are right, the way HTML5 treats closing tags is inconsistent. Specifying them on “void tags” has no effect, which makes sense because specifying a self-closing tag on tags the browser has hard-coded to be closed is logically redundant. However specifying self-closing tags on non-void tags also has no effect, which is so stupid it makes it seem like W3C were asleep at the wheel when they decided that.
The following should not recognize the alert as javascript because the tag is explicitly self-closed. However the fact that the script tag is explicitly closed gets completely ignored under the HTML standard.
This isn’t a rant over bizarre academic edge cases either, most web pages with external scripts have to deal with this bad decision. This doesn’t work even though by any reasonable measure it should…
It doesn’t work because HTML has completely butchered self closing tags. It needs to be written one of these two ways…
Even though self-closing tags aren’t required, if they’re going to bother adding them to the spec then the least they should have done is to make sure the semantics were right! It makes absolutely no sense that they’ve specified closing tags in a way that is semantically wrong. W3C made a string of unforced bad decisions. Ugh.
I started learning HTML before I entered college, and I never closed tags that didn’t explicitly require it because I learned by copying other people’s code, and they didn’t do it so I had no idea it was even a thing. This was the mid-late 90s mind you, I was fresh out of high school but delayed entering college because I was battling cancer at 18 years old; I had nothing else to do all day but browse the newfangled Web and learn how it was constructed.
Once I was able to go to college in 2001, I was ahead of the curve a bit thanks to my self-learning endeavors, but like any other academic environment I had to learn the “proper” way to write HTML code, which meant closing every paragraph and list and line break. My complaint was that my way worked just fine, the instructor’s response was if I learned it the “right” way I could get a job more easily, then once I had the job I could do it the way I wanted as long as it worked. Joke was on them, I pivoted from web development to networking and database management courses since that interested me more than making silly websites. Now I’m a sysadmin and I rarely have to touch HTML anymore, but when I do, I don’t close my damn tags unless I have to.
Now get off my lawn while I hang this onion from my belt and yell at that cloud over there. 😉
Morgan,
This probably doesn’t describe you, but from your narrative I am picturing a rebellious DB admin who carries a disregard for the “right way” from their HTML years into their SQL career. String concatenation everywhere instead of value parameters leading to SQL injection faults. Over rely on full page caches to mask bad query performance. Etc.
I take some pride in optimizing for high performance and it irks me whenever I see other software getting away with being so poorly optimized. I’m dealing with one right now and it’s atrocious! It must have been some punk HTML dev turned SQL admin. J/K 🙂
In truth I think corporate cheapness is responsible for making us rely more on faster hardware instead of software & database optimization. Many of us working at the companies know that these systems are faulty and sub-optimal but there’s constant pressure to do things on the quick and cheap. Giving a good DBA & coder enough time to build things right does make a big difference, but a “good“ project manager knows that the demo won’t exhibit these issues and leave it to be someone else’s problem on someone else’s dime. Haha.
Sadly I don’t really do much DBMS stuff these days, it’s mostly just managing our Windows servers and workstations, and dealing with ornery software like QuickBooks Enterprise Desktop and crappy web-based shipping software. I do help our two front-end website folks with more technical back-end stuff from time to time so that’s fun.
If the company owner had it her way we’d all be using Macs, which would be my excuse to run Linux on our file servers, but sadly Intuit says our company files are simply too big to import into QBO so we are stuck with 25+ year old legacy cruft not only with our desktop and server OSes, but with our accounting and inventory software as well. (To be clear, we are running recent, supported versions of Windows Server, and Win11 on the desktop, as well as up to date QBED, they both are just so rooted in legacy garbage that it’s painful on a daily basis.)
I do get a kick out of being the bane of Intuit’s existence though. It’s a truly shitty company.
Morgan,
These problems are extremely common with quickbooks. Almost every client I have seems to have their own issues with it. How they succeeded at business is a mystery since no one has positive things to say about it. It was clunky software decades ago and you’re right it’s still rooted in legacy garbage. To make matters worse Intuit intentionally denies users from exporting full IIF files, which is a documented restriction. They state that transaction data can’t be exported (only imported), but you’d only learn about it after you have a need to export it. Even the reports won’t output full untruncated data fields. One client ended up buying a Saasant subscription just to export their own data from quickbooks. Saasant works by automating the quickbooks GUI process to export data one field a time, which takes eons but at least bypasses Intuit’s export restrictions. As much as I hate vendor lock-in, it seems to be doing the job in keeping Intuit’s customers locked in.
Indeed, we had to hire an accounting firm just to attempt to export our company files in a way we could then import into QBO, only for Intuit to tell us our files are “too big for QBO”. Granted, the company (companies actually, two under the same owner and I work for both) has been around since the early 80s, and started using QBED in 2001.
My understanding is that the accountants are attempting a combination of writing off, consolidating, and archiving old transactions that don’t impact the business going forward, basically only keeping active what we may need for audits and such and trying to get the file sizes down. I honestly don’t know if it’s even possible to get both company files into a manageable size. They were supposed to be done by the end of 2025 but they aren’t even close to halfway there.
i’ve come to the conclusion the only way to run QuickBooks in a business environment is with a remote desktop server. One of my customers’ data file is now over 2 GB in size and it runs shockingly well, especially since QB says 1 GB is the recommended limit. Over the network it was completely unusable at time.
Our main company file is 1.3GB and the other, newer one is 650MB. That main file is the one Intuit says is “too big” for QBO. It actually works fairly well over our network, so I guess I’m doing something right. We can’t use QB over a wireless connection though, that’s always been the case and for those employees who need access from their untethered laptop, I use NoMachine to remote them into a wired workstation running the software.
gorbie,
It doesn’t have a normal client/server architecture, but uses operating system primitives and locking across SMB. Having different clients accessing the raw file makes it more vulnerable to fragmentation, contention and even corruption. But in terms of performance, this means that critical sections (ie locking and synchronizations) take place across a network with latency involved instead of in a local daemon. This is why it’s always scaled so poorly over a connection with moderate latency such as a remote user or even wifi. Quickbooks gets overwhelmed on operations that are paltry for a regular databases like MSSQL/MySQL/Oracle/etc. If you’re a single user accessing one record at a time on a local computer, it might be ok, but running a report or backup across the whole dataset quickly reveals how bad things are with quickbooks. Excel, albeit the wrong tool for the job, can perform the same actions in real time. It’s really kind of alarming how quickly quickbooks becomes saturated by it’s own overhead.
Quickbooks continues to be the standard in accounting despite how ridiculously sub par their database technology is. Proves that with the right sales pitch and partnerships it doesn’t matter that the product is shit.
While it’s true that you mostly don’t have to worry about closing your tags today, that wasn’t the case a long while ago, in the late 90s, or all o the 2000s, when IE6 was still choking the life out of progress on the web (leaving a wide open space for Flash.) In those days, the browsers would all behave differently, depending on where you leave out the closing tags. What the browser engines do is basically insert the closing tag (or just figuring out where followup objects should go when building the dom), and there wasn’t really a standard back then – no acid tests, just different browsers doing different things. The way many wanted to fix that back then was to add more static language like constraints, with more prescribed and rigid rules, like XHTML. This all changed when we finally got a push to sanity and just standardized the automatic closure behavior, and then tested it all with those old ACID tests. But yeah, it wasn’t so simple back in the day. It is now though!
I must be against the current but I think it was a mistake that HTML5 is not XML-only
jgfenix
That certainly would have made HTML much easier to parse and manipulate programatically outside of the browser using ordinary XML tools. The loose nature of HTML makes it harder to read the structural data and weak validation makes it easy for creators to make mistakes and not detect them.
Making a long page by hand can easily result in mismatched div/form/table fields and HTML browsers will still render them yet the errors mean styles and structures will be subtly wrong.
Not only that, it would make easier to integrate external data sources, generate HTML pages from .odt files for example or to extend the language using XML namespaces.
If I were a webpage creator I would try to only use XHTML5.
Why? The error correction behavior of HTML is well defined, and standardized. It gets parsed to DOM either way, and HTML is more flexible/forgiving. Translating .odt files to HTML is just as easy as translating to XML or XHTML.
CaptainN-,
There is an element of “we can’t get there from here”. Stricter browsers would be unusuable since they wouldn’t render existing websites. But if standard webrowsers had been designed around valid XML from day one then XHTML would have become the norm.
HTML does get parsed to a browser DOM, but it is annoying when your standard XML toolkit DOMs are broken by HTML that doesn’t validate. I’ve run into this with several projects. They are so close it would have made sense to merge them initially, but I think it’s practically impossible to rectify this now.
C is also more forgiving than Rust. It’s just the same.
The C to HTML comparison isn’t valid, IMHO. C is logic, HTML is just structure. The end result you get from parsing HTML – even when invalid, is consistent enough that you really don’t have to worry about exacting semantics of XML. I get the older arguments, and it did seem like we tried to get to XHTML for like a decade. But I maintain, there’s a strong reason why the industry went back to the more flexible HTML, and it wasn’t just because “we can’t get there from here.” The HTML format is more flexible and more forgiving. These characteristics are important for an “open web.”
CaptainN-,
The insight there isn’t distinguishing between logic and structure, but instead it’s about having a robust representation for these things. Say that instead of strict adherence to the rules, C compilers started to accept more syntax errors like missing semicolons., which would normally produce an error, but the compiler could just ignore/fix the errors under the hood. It’s pretty obvious that the consequence of compilers doing that would result in a code base that becomes increasingly error prone and compilers would be forced to start including heuristics to fix these errors. This is kind of the situation HTML is in right now. We make it work, but the result is that a lot of HTML websites can contain tag/mismatch errors and get left this way because the browsers haven’t put a stop to it.
HTML is more lenient about adherence to strict standards, but it isn’t more flexible or open though in terms of expressibility. XML even has features that are lacking in HTML.
It’s not really any more difficult to do things right and in an alternate evolutionary path where HTML tags were validated I don’t believe there would be demand for a browser that allows errors any more than there is demand for a C compiler that allows syntax errors – both of these are non-goals. It’s hard to get there today given that our evolutionary path has allowed websites to contain broken HTML tags and still render something potentially useful. But if we could get to that alternate evolutionary reality there would be no incentive to come back. This is why I say it would be better but “you can’t get there from here”. Few would be complaining about browsers enforcing tag semantics from day one because 100% of websites would be compliant just like 100% of C programs need to be syntactically valid to compile. That’s not a weakness but a strength.
You are against the current – and for good reason. XHTML was brittle, and the browsers had to compensate for a lot of broken document structures out in the real world anyway. It turned out to be easier to just standardize the behavior of incomplete and incorrect code. That flexibility is a strength of HTML, not a weakness.
Unfortunately worse is better. The fact that PHP was string-based didn’t help.
Yes, you had to in the past, in HTML5 it’s properly and exactly defined how to handle these cases so all browsers render it the same.
So put in a HTML5-doctype and you should get the same results when you leave off a bunch of the end tags.
Lennie,
Indeed it’s true that we can standardize the way browsers respond to missing and mismatching tags, however it doesn’t imply that this was the best evolutionary path for HTML.
In a situation where standards are forced to acknowledge and standardize the widespread use of broken tags, the best we can do is make sure all browsers handle them in the same way. However at the moment of inception it would have arguably been better to mandate correct tags before the proliferation of documents & websites with bad tags took place. The simple act of having browsers display these errors rather than ignoring them would have placed us on the evolutionary path emphasizing correctness.