HTML Comments: Notes That Ship With Your Code
Comments explain markup to the next developer, but they are downloaded by every visitor and readable by anyone. Learn the syntax, the nesting trap and what must never go inside one.
-
HTML Basics
- What is HTML: The Structure Layer of Every Web Page
- HTML Document Structure: DOCTYPE, html, head and body
- Elements, Tags and Attributes: The Vocabulary of HTML
- HTML Comments: Notes That Ship With Your Code
- Block Level and Inline Elements
- Writing and Running Your First HTML Page
- How a Browser Turns Markup Into a Page
- Text and Formatting
- Links and Navigation
- Images and Media
- Lists
- Tables
-
Forms
- Form Structure: form, action and method
- Input Types: Text, Email, Number, Date and the Rest
- Labels: The Most Important Element in a Form
- Checkboxes, Radio Buttons and Grouping
- select, option, optgroup and datalist
- textarea, File Uploads and Hidden Fields
- Buttons: submit, reset and button
- Built In Form Validation
- GET or POST: What Happens When a Form Is Submitted
- Semantic HTML
- HTML5 Features
- Head and Metadata
- HTML with CSS
- HTML with JavaScript
- Accessibility
-
HTML SEO
- How Google Works: Crawling, Indexing and Ranking
- SEO Friendly HTML Structure
- Titles and Descriptions That Earn Clicks
- Headings and Content Structure for Search
- Internal Linking and Anchor Text
- robots.txt and XML Sitemaps
- Canonical URLs and Duplicate Content
- Structured Data and JSON-LD
- Image SEO
- Core Web Vitals and Mobile Friendliness
- DevTools and Debugging
- Editor Productivity
- HTML Best Practices
- HTML Projects
- Advanced Projects
- Practice and Exams
Concept
A comment is a note in the source that the browser ignores. It is not drawn, it does not become a DOM element that CSS or layout can touch, and it never affects rendering. What it does do is travel: the comment is inside the file that every visitor downloads, and anyone can read it from the page source.
Syntax
<!-- a single line comment -->
<!--
A comment across
several lines.
-->
<!-- <p>Temporarily disabled markup.</p> -->The opening delimiter is an angle bracket, an exclamation mark and two hyphens. The closing delimiter is two hyphens and an angle bracket. Both are exact; there is no shorter form and no line comment.
Example
<!-- Pricing table
Columns are generated by the server from the plans table.
The order matters: the middle column is styled as the highlighted plan,
so do not reorder without updating pricing.css as well. -->
<table class="pricing">
<caption>Subscription plans, billed yearly</caption>
<!-- ... rows ... -->
</table>
<!-- TODO: replace with the responsive gallery once the image CDN is live -->
<img src="/images/hero.jpg" alt="Team standing outside the workshop">Explanation
The first comment earns its place because it records a constraint that the markup itself cannot express: a hidden coupling between column order and a stylesheet rule. Someone reordering the columns six months from now would otherwise break the design and have no idea why.
The second comment is a reminder. It is fine in a working branch and should not survive to production, because a note about unfinished infrastructure is exactly the sort of thing that should not be public.
The nesting trap
Comments do not nest. The parser ends the comment at the first closing delimiter it meets, so an inner comment terminates the outer one early and everything after it becomes live markup again.
<!-- outer
<!-- inner -->
<p>This paragraph is NOT commented out. It renders.</p>
-->The stray --> on the last line then shows up as text on the page. This bites most often when commenting out a block that already contains comments. Remove the block or wrap it in a way that has no inner delimiters.
Important rules
- Two consecutive hyphens inside a comment are not allowed. Write see note, not see -- note.
- A comment must not end with a hyphen immediately before the delimiter.
- Comments are visible to every visitor through view source. They are not private.
- They are downloaded on every uncached request, so they cost bandwidth.
- Conditional comments, which once targeted old versions of Internet Explorer, are dead. No current browser honours them.
What must never go in a comment
- Passwords, API keys, tokens or connection strings, even commented out.
- Internal URLs, staging hostnames, admin paths or server names.
- Notes about known vulnerabilities, unpatched bugs or the state of the security work.
- Names of clients or staff, and anything else you would not put on the page itself.
- Large blocks of commented out markup left in place for months. Version control already remembers deleted code, and does it better.
Common mistakes
- Assuming a comment is private because it is not visible on the page.
- Nesting comments and wondering why part of the block still renders.
- Using a comment to hide content from the reader while expecting a crawler to still index it. Commented markup is not content at all.
- Leaving a half typed delimiter, which silently swallows every element after it until the next closing sequence appears.
- Explaining what the markup obviously does - this is the header above a
headerelement - rather than why it is the way it is.
Best practices
- Comment the why, never the what. Good markup already states what it is.
- Use comments to mark the ends of long regions:
<!-- /site-header -->saves real time in a deeply nested file. - Strip comments from production with a build step if the file is large; keep them in source.
- Delete commented out markup rather than parking it. If it might come back, it belongs in a commit, not in the file.
- Prefer a comment that names a decision and a date over one that names a person.
Practice
- Write a comment for a navigation block that explains a constraint a future developer could not guess from the markup.
- Try to comment out a block that already contains a comment. Predict where the output breaks, then confirm it in the browser.
- Open the page source of any site you use and count how many comments reveal a framework, a build tool or a file path. What could someone do with that information?