Learn HTML best practices including W3C validation, performance optimization with script loading strategies, progressive enhancement, and common mistakes to avoid.
The W3C Markup Validation Service checks your HTML against the specification and reports errors and warnings. Valid HTML ensures:
| Error | Fix |
|---|---|
Missing alt on <img> | Add alt attribute (use alt="" for decorative images) |
| Unclosed elements | Ensure every opening tag has a matching closing tag |
Duplicate id attributes | Each id must be unique on the page |
Block elements inside <p> | Move block elements outside the paragraph |
Missing <!DOCTYPE html> | Always start with the doctype declaration |
Obsolete elements (<center>, <font>) | Use CSS instead |
Make validation part of your workflow — run it during development, not just before launch.
How you load JavaScript affects page performance. The key attributes on <script> are:
defer<script src="app.js" defer></script>async<script src="analytics.js" async></script>type="module"<script type="module" src="app.js"></script>import/export.<link rel="preload"> — Fetch a resource immediately (fonts, critical CSS).<link rel="prefetch"> — Fetch a resource for future navigation (low priority).<link rel="preconnect"> — Establish early connection to a third-party origin.<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>Progressive enhancement is a strategy that starts with a baseline of functional HTML and layers on CSS and JavaScript as enhancements.
<a href="/page"> for navigation (works without JS). Enhance with client-side routing.<form action="/submit"> for data submission (works without JS). Enhance with AJAX.<details>/<summary> for collapsible content (works without JS). Enhance with animations.<dialog> for modals (works without complex JS).The opposite approach — graceful degradation — starts with a full-featured experience and tries to make it work in limited environments. Progressive enhancement is generally preferred because it guarantees the baseline works everywhere.
<div> for everything — Use semantic elements (<nav>, <main>, <section>, <article>, <aside>, <header>, <footer>).<h1> to <h3>. The document outline should be logical.<br> for spacing — Use CSS margin and padding instead.lang on <html> — Always declare the document language.width and height to prevent layout shift.<table> for layout — Tables are for tabular data only.HTML is a living standard maintained by WHATWG. There are no version numbers ("HTML5" is a marketing term). The specification is continuously updated at html.spec.whatwg.org.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A well-structured HTML page example">
<!-- Preconnect to external origins -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<title>Best Practices Example</title>
<!-- CSS: non-blocking -->
<link rel="stylesheet" href="styles.css">
<!-- JS: deferred -->
<script src="app.js" defer></script>
</head>
<body>
<a href="#main" class="skip-link">Skip to content</a>
<header>
<nav aria-label="Primary">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main id="main">
<article>
<h1>Page Title</h1>
<p>Content goes here.</p>
<img src="photo.jpg" alt="Description" width="800" height="600" loading="lazy">
</article>
</main>
<footer>
<p>© 2025 Example Site</p>
</footer>
</body>
</html>What is the difference between the `defer` and `async` attributes on a <script> tag?