~/hackweb.dev
HTML Best Practices
Quiz
...

HTML Best Practices

beginner · updated Tue Sep 08 2026Contribute

Master code organization, naming, performance, and security best practices.

HTML Best Practices

Writing clean, maintainable HTML improves collaboration, performance, and security. These practices help you write professional-quality code.

Code Organization

Indentation

Use consistent indentation (2 or 4 spaces):

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My Page</title>
  </head>
  <body>
    <header>
      <nav>
        <ul>
          <li><a href="/">Home</a></li>
        </ul>
      </nav>
    </header>
  </body>
</html>

Line Length

Keep lines under 80-100 characters:

<!-- Bad: Long line -->
<img src="very-long-image-path/that-keeps-going/and-going.jpg" alt="A very long alt text that describes the image in great detail for accessibility" />

<!-- Good: Shorter lines with attributes on separate lines -->
<img
  src="very-long-image-path/that-keeps-going/and-going.jpg"
  alt="A very long alt text that describes the image in great detail for accessibility"
/>

Logical Structure

Organize elements logically:

<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Meta tags first -->
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- Title -->
    <title>Page Title</title>

    <!-- Styles -->
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <!-- Header -->
    <header>
      <nav><!-- Navigation --></nav>
    </header>

    <!-- Main content -->
    <main>
      <article><!-- Article content --></article>
    </main>

    <!-- Footer -->
    <footer><!-- Footer content --></footer>

    <!-- Scripts at end -->
    <script src="app.js"></script>
  </body>
</html>

Naming Conventions

Class Names

Use descriptive, kebab-case class names:

<!-- Bad: Generic or unclear names -->
<div class="box">
<div class="red">
<div class="container-1">

<!-- Good: Descriptive names -->
<div class="product-card">
<div class="error-message">
<div class="main-container">

Rules:

  • Use lowercase
  • Use hyphens (kebab-case): nav-item not navItem
  • Be descriptive: user-profile not profile
  • Avoid abbreviations: navigation not nav (unless obvious)

ID Names

Use IDs sparingly, only for JavaScript or CSS hooks:

<!-- Good: IDs for JavaScript -->
<div id="user-dashboard">
<button id="submit-form">

<!-- Bad: IDs for styling -->
<div id="sidebar" class="sidebar"> <!-- Use class instead -->

HTML Structure

DOCTYPE

Always include DOCTYPE:

<!DOCTYPE html>

Language Attribute

Always set the language:

<html lang="en">

Character Encoding

Always include charset first:

<meta charset="UTF-8" />

Viewport

Always include for responsive design:

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

Semantic HTML

Use elements for their meaning:

<!-- Bad: Using divs for everything -->
<div class="header">
<div class="nav">
<div class="content">
<div class="footer">

<!-- Good: Using semantic elements -->
<header>
<nav>
<main>
<footer>

Performance

Optimize Images

Always specify dimensions:

<!-- Bad: Causes layout shift -->
<img src="photo.jpg" alt="Photo" />

<!-- Good: Prevents layout shift -->
<img src="photo.jpg" alt="Photo" width="800" height="600" />

Lazy Loading

Load images only when visible:

<img src="photo.jpg" alt="Photo" loading="lazy" />

Minimize HTTP Requests

Combine and minify:

<!-- Bad: Multiple files -->
<link rel="stylesheet" href="header.css" />
<link rel="stylesheet" href="content.css" />
<link rel="stylesheet" href="footer.css" />

<!-- Good: Single file -->
<link rel="stylesheet" href="styles.min.css" />

Security

Escape User Input

Always escape user-generated content:

<!-- User input -->
<script>alert('xss')</script>

<!-- Escaped (safe) -->
&lt;script&gt;alert('xss')&lt;/script&gt;

Use HTTPS

Always use HTTPS:

<!-- Bad -->
<a href="http://example.com">Link</a>

<!-- Good -->
<a href="https://example.com">Link</a>

Set Content Security Policy

Prevent XSS attacks:

<meta
  http-equiv="Content-Security-Policy"
  content="default-src 'self'; script-src 'self'"
/>

Validate Input

Never trust user input:

<!-- Always validate on server -->
<form action="/submit" method="POST">
  <input type="email" name="email" required />
</form>

Accessibility

Label All Inputs

Every input needs a label:

<!-- Bad -->
<input type="text" name="email" />

<!-- Good -->
<label for="email">Email</label>
<input type="email" id="email" name="email" />

Use Semantic Elements

Semantic elements are more accessible:

<!-- Bad -->
<div onclick="handleClick()">Click me</div>

<!-- Good -->
<button onclick="handleClick()">Click me</button>

Add Alt Text

All images need alt text:

<!-- Bad -->
<img src="photo.jpg" />

<!-- Good -->
<img src="photo.jpg" alt="A sunset over mountains" />

Complete Example

Here’s a complete, well-structured HTML file:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Best Practices Example</title>
    <meta name="description" content="Example of HTML best practices" />
    <link rel="stylesheet" href="styles.min.css" />
  </head>
  <body>
    <!-- Skip link for accessibility -->
    <a href="#main-content" class="skip-link">
      Skip to main content
    </a>

    <!-- Header -->
    <header class="site-header">
      <nav class="main-navigation" aria-label="Main navigation">
        <ul class="nav-list">
          <li class="nav-item">
            <a href="/" class="nav-link" aria-current="page">Home</a>
          </li>
          <li class="nav-item">
            <a href="/about" class="nav-link">About</a>
          </li>
        </ul>
      </nav>
    </header>

    <!-- Main Content -->
    <main id="main-content" class="main-content">
      <article class="blog-post">
        <header class="post-header">
          <h1 class="post-title">Article Title</h1>
          <time class="post-date" datetime="2026-09-08">
            September 8, 2026
          </time>
        </header>

        <div class="post-content">
          <p>Article content here...</p>

          <figure class="post-image">
            <img
              src="photo.jpg"
              alt="Descriptive alt text"
              width="800"
              height="600"
              loading="lazy"
            />
            <figcaption class="image-caption">
              Figure 1: Image description
            </figcaption>
          </figure>
        </div>

        <footer class="post-footer">
          <p class="post-tags">
            Tags:
            <a href="/tag/html" class="tag">HTML</a>,
            <a href="/tag/best-practices" class="tag">Best Practices</a>
          </p>
        </footer>
      </article>
    </main>

    <!-- Footer -->
    <footer class="site-footer">
      <nav class="footer-navigation" aria-label="Footer navigation">
        <ul class="footer-links">
          <li>
            <a href="/privacy" class="footer-link">Privacy</a>
          </li>
          <li>
            <a href="/terms" class="footer-link">Terms</a>
          </li>
        </ul>
      </nav>
      <p class="copyright">&copy; 2026 My Site. All rights reserved.</p>
    </footer>

    <script src="app.min.js"></script>
  </body>
</html>

Checklist

Structure:

  • DOCTYPE included
  • Language attribute set
  • Character encoding set
  • Viewport meta tag

Semantics:

  • Semantic elements used
  • Proper heading hierarchy
  • Landmark roles where needed

Accessibility:

  • All images have alt text
  • All inputs have labels
  • Keyboard navigation works
  • Screen reader tested

Performance:

  • Images optimized
  • Lazy loading enabled
  • CSS/JS minified
  • No unnecessary requests

Security:

  • HTTPS used
  • User input escaped
  • CSP header set

Common Mistakes

  1. Not using semantic HTML — Use divs only when necessary
  2. Missing alt text — All images need alt attributes
  3. No viewport meta — Site won’t work on mobile
  4. Inline styles — Use CSS files instead
  5. Ignoring accessibility — Test with screen readers
  6. Not validating code — Use W3C validator
  7. Hardcoding paths — Use relative URLs
  8. Over-nesting — Keep HTML flat when possible