HTML Best Practices & SEO
Clean HTML is easier to read, easier to fix and easier for Google to understand. This chapter collects the habits professional developers follow.
Clean Code Habits
| Habit | Example |
|---|---|
| Start with the doctype and language | <!DOCTYPE html> and <html lang="en"> |
| Use lowercase tags and attributes | <section class="intro">, not <SECTION CLASS="intro"> |
| Always quote attribute values | class="card big", not class=card big |
| Close elements you open | <p>...</p>, <li>...</li> |
| Indent nested elements | Two or four spaces per level, the same everywhere |
| Use lowercase file names with hyphens | about-us.html, team-photo.jpg |
| Keep CSS and JS in separate files | <link href="style.css">, <script src="app.js" defer> |
| Use semantic elements | <nav>, <main>, <article> instead of many <div> |
A Clean Starter Template
Most of your pages can start from this template:
Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Topic | Site Name</title>
<meta name="description" content="One or two sentences that describe this page.">
<link rel="icon" href="/favicon.ico">
<link rel="stylesheet" href="/css/style.css">
<script src="/js/app.js" defer></script>
</head>
<body>
<header>
<nav>
<a href="/">Home</a>
<a href="/courses">Courses</a>
</nav>
</header>
<main>
<h1>Page Topic</h1>
<p>Main content goes here.</p>
</main>
<footer>
<p>© 2026 Site Name</p>
</footer>
</body>
</html>Try it Yourself »defer on the script tag means: download the JavaScript while the page loads, but run it only after the HTML is ready. The page appears faster.
Check Your HTML
Mistakes like a missing </div> can break a layout in strange ways. Test your page with an HTML validator, such as the free W3C Markup Validation Service. Paste your code, and it lists every error with its line number.
SEO Recap
You learned the basics in HTML Head, Meta & SEO Basics: a unique title, a meta description, one <h1>, alt text, good link text and semantic tags. Here are the extra tags that professional sites add.
Canonical Link
If the same page can be opened at more than one address (for example with and without ?ref=facebook), tell Google which address is the real one:
Example
<link rel="canonical" href="https://www.example.com/courses/web-development">Robots Meta Tag
Control whether Google shows a page in its results:
Example
<!-- do not show this page in search results -->
<meta name="robots" content="noindex">Use it for thank-you pages, test pages and private areas. Leave it out on normal pages, since indexing is the default.
Open Graph and Social Previews
When a link is shared on WhatsApp, Facebook or LinkedIn, the app reads Open Graph tags to build the preview card. X (Twitter) reads its own twitter: tags, and falls back to Open Graph.
Example
<head>
<meta property="og:type" content="website">
<meta property="og:title" content="Web Development Course in Karachi">
<meta property="og:description" content="Learn HTML, CSS and JavaScript with real projects.">
<meta property="og:image" content="https://www.example.com/images/share-card.jpg">
<meta property="og:url" content="https://www.example.com/courses/web-development">
<meta property="og:site_name" content="Example Institute">
<meta name="twitter:card" content="summary_large_image">
</head>| Tag | Notes |
|---|---|
og:title | The headline of the card, can differ from <title> |
og:description | One or two sentences |
og:image | A full https address; 1200 x 630 pixels works well |
og:url | The canonical address of the page |
twitter:card | summary_large_image shows a big picture |
Open Graph tags use property=, not name=. A small mistake here means the preview does not show.
Structured Data with JSON-LD
Structured data describes your page in a format machines understand: "this is a business, here is its address and phone number" or "this is a course". Google can use it to show richer results, such as stars, prices or a business panel.
The recommended format is JSON-LD, written in a <script> tag with the type application/ld+json. It can go in the head or the body, and it does not change what visitors see.
Example
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Ali Computers",
"telephone": "+92-300-1234567",
"address": {
"@type": "PostalAddress",
"streetAddress": "Shop 12, Main Road",
"addressLocality": "Karachi",
"addressCountry": "PK"
},
"openingHours": "Mo-Sa 10:00-21:00"
}
</script>| Key | Meaning |
|---|---|
@context | Always https://schema.org, the shared vocabulary |
@type | What the thing is: LocalBusiness, Course, Article, Product, FAQPage... |
| Other keys | The details for that type, like name and address |
A course page could use the Course type:
Example
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Course",
"name": "Web Development",
"description": "HTML, CSS and JavaScript from zero, with real projects.",
"provider": {
"@type": "Organization",
"name": "Example Institute"
}
}
</script>Rules for structured data:
- Describe only what is really on the page. Fake reviews or prices can get a site penalised.
- JSON must be valid: double quotes, commas between items, no comma after the last one.
- Test it with Google's free Rich Results Test before publishing.
Final Checklist
- Valid HTML with doctype,
lang, charset and viewport - A unique title and description on every page
- Semantic layout and headings in order
- alt text, labels and keyboard access (HTML Accessibility)
- Fast images with
srcsetandloading="lazy" - Open Graph tags for sharing and JSON-LD where it fits
Exercise
Exercise
Which script type is used for JSON-LD structured data?
