HTML Best Practices
This lesson gathers the habits that separate HTML that merely displays from HTML that's accessible, maintainable and robust. Most of them have come up earlier in the course; here they're collected as a checklist you can keep coming back to.
Document setup
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Page topic — Site name</title> <meta name="description" content="A useful one-sentence summary of this page."> <link rel="icon" href="/icon.svg" type="image/svg+xml"> <link rel="stylesheet" href="/css/styles.css"> <script src="/js/app.js" defer></script> </head> <body> <a class="skip-link" href="#main">Skip to content</a> <header>…</header> <main id="main">…</main> <footer>…</footer> </body> </html>
- Always include the doctype,
lang,charset,viewportand a uniquetitle. - Load CSS in the head and scripts with
defer.
Meaning first
- Choose elements for what content is, not how it should look: headings for headings, lists for lists, buttons for actions, links for navigation.
- Use landmarks —
<header>,<nav>,<main>,<footer>— and keep heading levels in order. - Reach for
<div>and<span>only when no semantic element fits. - Keep presentation in CSS: no
<br>for spacing, no tables for layout, minimal inline styles.
Code style
<!-- ✓ consistent, readable --> <ul class="product-list"> <li class="product-list__item"> <a href="/products/lamp">Desk lamp</a> </li> </ul> <!-- ✗ inconsistent and hard to read --> <UL Class=ProductList><li><A HREF='/products/lamp'>Desk lamp</a></UL>
- Lowercase element and attribute names; double-quoted attribute values.
- Indent nested elements consistently (2 spaces is common).
- Close all non-void elements, even where optional.
- Use lowercase, hyphenated file names and class names that describe purpose.
- Let a formatter such as Prettier handle spacing and indentation automatically.
Accessibility habits
- Meaningful
alttext on every image (oralt=""for decoration). - A connected label for every form control; fieldsets for groups.
- Descriptive link and button text; accessible names for icon buttons.
- Visible focus styles and full keyboard support.
- Sufficient colour contrast, and never colour as the only signal.
- Captions and transcripts for media.
Performance habits
widthandheighton images, video and iframes.loading="lazy"below the fold;fetchpriority="high"on the hero image.- Responsive images with
srcset/<picture>and modern formats. - Fewer, deferred scripts.
Forms
- The right input
type,autocompleteandinputmodefor each field. - Explain requirements before people type; keep error messages specific.
type="button"on buttons that don't submit.- Validate on the server too, always.
Security
- Never put secrets (API keys, passwords) in HTML, comments or client-side scripts.
- Escape user content: insert it as text, never as raw HTML.
- Use HTTPS everywhere, especially for forms.
- Sandbox third-party iframes; add
rel="noopener"to links that open new tabs; use Subresource Integrity for CDN scripts.
Quality checks before publishing
- Validate the HTML.
- Tab through every page with the keyboard.
- Run Lighthouse for accessibility, performance and SEO.
- Test on a real phone, and at 200% zoom.
- Check the page title, description and social preview.
- Click every link — broken links frustrate users and search engines alike.
Progressive enhancement
Build in layers: first HTML that works on its own (content readable, links followable, forms submittable), then CSS for presentation, then JavaScript for enhancements. If the CSS or JavaScript fails to load — which happens more often than you'd think on mobile networks — the page still works.
Keep learning
MDN Web Docs is the most reliable HTML reference, with compatibility tables for every element and attribute. The HTML Living Standard itself (from WHATWG) is the definitive specification. And "View Page Source" on well-built sites remains one of the best teachers.