Chapter 1 — Introduction to Web Development

Learning Outcome

Understand the role of HTML in web development and how websites work.

Next → 02 - Document Structure & Syntax

1.1 What is HTML?

HTML stands for HyperText Markup Language.

  • It is the standard language used to create and structure content on the web.
  • HTML is not a programming language — it is a markup language.
  • It tells the browser how to display content using a system of elements represented by tags.

From W3Schools

"HTML is the standard markup language for creating Web pages."

1.2 HTML vs CSS vs JavaScript

The three core technologies of the web each play a distinct role:


Key Insight

You can build a webpage with HTML alone. CSS and JS enhance it — but HTML is the foundation every single time.

1.3 How Websites Work

When you type a URL in the browser, this happens:

  1. Your browser sends an HTTP request to a web server.
  2. The server sends back an HTML file.
  3. The browser parses (reads) the HTML and renders the page.
  4. CSS and JS files linked in the HTML are then fetched and applied.
User → types URL → Browser → HTTP Request → Web Server
Web Server → HTML file → Browser → Renders page → User sees it

HTTP vs HTTPS

HTTPS is the secure version of HTTP. The "S" means the connection is encrypted. Always use HTTPS for real websites.

1.4 Types of Websites

Recommended Projects

Project 1 — "About Me" Static Page

Create a simple page with your name, a short bio, and a fun fact. Rules: No CSS. Pure HTML only. Practice structure, not style.

Project 2 — Web Tech Comparison Sheet

Build a 2-column HTML page showing HTML vs CSS vs JS responsibilities. Use only headings and paragraphs. No tables yet.

📌 Quick Recall

  • HTML = HyperText Markup Language
  • HTML → Structure | CSS → Style | JS → Behaviour
  • Browser sends HTTP request → Server returns HTML → Browser renders it
  • HTML is a markup language, not a programming language

Next → 02 - Document Structure & Syntax

Chapter 2 — HTML Document Structure & Syntax

Learning Outcome

Create a valid HTML5 page with correct document structure from scratch.

01 - Introduction to Web Development | Next → 03 - Tags Elements & Attributes

2.1 DOCTYPE Declaration

Every HTML5 document must begin with <!DOCTYPE html>.

<!DOCTYPE html>
  • Tells the browser which version of HTML is being used.
  • Without it, browsers enter "quirks mode" and render inconsistently.
  • Always place it on the very first line.

Don't Skip DOCTYPE

Missing <!DOCTYPE html> causes unpredictable rendering across browsers — especially older ones.

2.2 The Root Structure

Every HTML page is built around 4 essential tags:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Page Title</title>
  </head>
  <body>
    <!-- All visible content goes here -->
  </body>
</html>


lang Attribute
Always add lang="en" (or your language code) on <html>. It helps screen readers pronounce content correctly and improves SEO.

2.3 The <head> Tag — In Detail

The <head> contains metadata — data about the document, not in it.

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="An HTML tutorial for beginners">
  <meta name="author" content="Your Name">
  <title>Page Title</title>
  <link rel="stylesheet" href="style.css">
  <link rel="icon" href="favicon.ico">
  <script src="app.js" defer></script>
</head>

2.4 HTML Syntax Rules

Core Syntax Rules

  1. Tags are written in lowercase (best practice)
  2. Most tags come in pairs — opening + closing: <p>…</p>
  3. Self-closing tags have no closing tag: <br>, <img>, <hr>
  4. Tags must be properly nested — inner tag closes before outer tag
  5. Attribute values go in double quotes
<!-- ✅ Correct nesting -->
<p><strong>Bold text</strong> in a paragraph.</p>

<!-- ❌ Wrong nesting -->
<p><strong>Bold text</p></strong>

2.5 HTML Boilerplate (Full Template)

Save this as your starting template for every new HTML file:

<!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="Page description here">
  <title>Document Title</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>

  <h1>Hello, World!</h1>

  <script src="app.js" defer></script>
</body>
</html>
VS Code Shortcut
In VS Code, type ! and press Tab — it auto-generates the full boilerplate instantly. (Requires Emmet, which is built-in.)

🚀 Recommended Projects

Project 1 — First Webpage

Create a complete HTML page with proper DOCTYPE, head, and body. Add a title, one <h1> heading, and two <p> paragraphs about your favourite subject.

Project 2 — Metadata Explorer

Create 3 different pages each with unique <meta> description tags and titles. Open them and observe how the browser tab changes.

📌 Quick Recall

  • <!DOCTYPE html> → always first line
  • <html> → root | <head> → metadata | <body> → visible content
  • charset="UTF-8" → supports all languages
  • viewport meta → mobile-responsive
  • VS Code shortcut: ! + Tab = full boilerplate

01 - Introduction to Web Development | Next → 03 - Tags Elements & Attributes

Chapter 3 — Tags, Elements & Attributes

Learning Outcome

Understand the difference between tags, elements, and attributes — and write structured HTML using them correctly.

02 - Document Structure & Syntax | Next → 04 - Text Formatting & Content

3.1 Tags vs Elements

These two words are often confused — they mean different things.

<!-- <p> is the opening TAG -->
<!-- </p> is the closing TAG -->
<!-- <p>Hello World</p> is the ELEMENT -->

<p>Hello World</p>

3.2 Paired vs Self-Closing Tags

Paired (normal) elements — have both opening and closing tags:

<h1>This is a heading</h1>
<p>This is a paragraph</p>
<a href="#">This is a link</a>

Self-closing / Void elements — no closing tag, no content:

<br>       <!-- line break -->
<hr>       <!-- horizontal rule / divider -->
<img src="photo.jpg" alt="A photo">
<input type="text">
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">

HTML5 vs XHTML

In HTML5 you write <br>. In XHTML you write <br />. Both are accepted in HTML5, but <br> is more common today.

3.3 Attributes — Syntax & Rules

Attributes provide extra information about an element. They sit inside the opening tag only.

Syntax:

attribute="value"
<img src="cat.jpg" alt="A tabby cat" width="300" height="200">
     ^^^            ^^^               ^^^^^         ^^^^^^
     attr           attr              attr           attr

Attribute Rules

  • Always written in the opening tag
  • Values go in double quotes
  • Multiple attributes separated by spaces
  • Attribute names are case-insensitive (lowercase is best practice)
  • Some attributes are boolean — just their name is enough: required, disabled, checked

3.4 Common Attributes

Universal Attributes (work on any tag)


<p id="intro" class="highlight" title="Welcome text">
  Hello, welcome!
</p>

<!-- data-* attribute example -->
<button data-user-id="42" data-role="admin">Edit</button>

Element-Specific Attributes

3.5 id vs class — Key Differences

<!-- id — unique landmark -->
<section id="about">...</section>

<!-- class — reusable style group -->
<p class="card-text">First card</p>
<p class="card-text">Second card</p>
<p class="card-text">Third card</p>

🚀 Recommended Projects

Project 1 — Personal Profile Card

Build an HTML profile card using <div>, <img>, <p>, <h2>, and <a>. Use id and class attributes to label each section. No CSS — just structure.

Project 2 — Attribute Showcase Page

Create a page demonstrating at least 8 different attributes: title, style, id, class, src, alt, href, placeholder. Add a comment above each element explaining which attribute you're demonstrating.

📌 Quick Recall

  • Tag = just <p> | Element = <p>content</p>
  • Void elements have no closing tag: <br>, <img>, <input>, <hr>, <meta>
  • id = unique (one per page) | class = reusable (many elements)
  • Attributes always go in the opening tag with attribute="value" syntax
  • Boolean attributes: required, disabled, checked — no value needed

02 - Document Structure & Syntax | Next → 04 - Text Formatting & Content


Chapter 4 — Text Formatting & Content

Learning Outcome

Format and structure textual content using HTML headings, paragraphs, and semantic text tags.

03 - Tags Elements & Attributes | Next → 05 - Links & Navigation

4.1 Headings — <h1> to <h6>

HTML provides 6 levels of headings.

<h1>Main Page Title</h1>
<h2>Section Heading</h2>
<h3>Sub-section Heading</h3>
<h4>Smaller Sub-heading</h4>
<h5>Minor Heading</h5>
<h6>Smallest Heading</h6>

Don't Skip Heading Levels

Don't jump from <h1> to <h4>. Use headings in logical order (h1 → h2 → h3). Skipping levels breaks accessibility and SEO.

SEO Importance

Search engines (Google) heavily use <h1> to understand what your page is about. Use one descriptive <h1> per page.

4.2 Paragraphs, Line Breaks & Dividers

<p>This is a paragraph. Browsers automatically add space above and below.</p>

<p>This paragraph has a line break inside it.<br>
This is on a new line within the same paragraph.<br>
And this is another line.</p>

<hr>

<p>This paragraph comes after the horizontal divider.</p>

Whitespace Collapsing

HTML ignores multiple spaces and newlines in source code — they all collapse to a single space. Use <br> for deliberate line breaks.

4.3 Semantic Text Formatting Tags

These tags carry meaning, not just visual style.

<p>This is <strong>very important</strong> text.</p>
<p>This is <em>emphasised</em> text.</p>
<p>Price was <del>₹500</del>, now <ins>₹300</ins>.</p>
<p>Water: H<sub>2</sub>O | Area: πr<sup>2</sup></p>
<p><mark>Highlighted</mark> term in a sentence.</p>
<p>Use the <code>console.log()</code> function.</p>
<p><abbr title="HyperText Markup Language">HTML</abbr> is fun.</p>


4.5 HTML Comments

<!-- This is a comment — the browser ignores it -->

<!--
  Multi-line comment.
  Great for leaving notes for yourself or your team.
-->

<!-- TODO: Add navigation bar here -->
<h1>Page Content</h1>

<!-- DISABLED:
<section class="old-promo">
  ...
</section>
-->

Don't Put Secrets in Comments

HTML comments are visible to anyone who opens DevTools (F12 → Inspector). Never put passwords, API keys, or sensitive data in HTML comments.

🚀 Recommended Projects

Project 1 — Blog Article Page

Write a fake blog article with:

  • <h1> title, <h2> section headings
  • Several <p> paragraphs
  • At least one <blockquote>
  • Uses of <strong>, <em>, <mark>
  • An <hr> divider between sections

Project 2 — Science Notes Page

Create chemistry/maths notes using:

  • <sub> for chemical formulas: H₂SO₄, CO₂
  • <sup> for powers: x², r³
  • <code> for equations
  • <pre> for aligned data tables or multi-line formulas

📌 Quick Recall

  • <h1> = one per page (main title) → <h6> = smallest heading
  • <p> = paragraph | <br> = line break | <hr> = divider
  • <strong> = important bold | <em> = emphasis italic
  • <sub> = subscript (H₂O) | <sup> = superscript (x²)
  • <code> = inline code | <pre> = preserves whitespace
  • Comments: <!-- ... --> | Visible in DevTools — never store secrets!

03 - Tags Elements & Attributes | Next → 05 - Links & Navigation



Chapter 5 — Links & Navigation

Learning Outcome

Create all types of hyperlinks and build navigation between pages.

04 - Text Formatting & Content | Next → 06 - Lists

5.1 The Anchor Tag <a>

The <a> (anchor) tag creates hyperlinks. The href attribute is the destination.

<a href="https://www.google.com">Visit Google</a>

Key Attributes

target Values

Security with target="_blank"

Always add rel="noopener noreferrer" when using target="_blank". Without it, the opened page can access and manipulate the original tab via JavaScript.

<a href="https://example.com" target="_blank" rel="noopener noreferrer">
  Open in new tab (safe)
</a>

5.2 Types of Links

Absolute URLs

Full address including the protocol.

<a href="https://www.w3schools.com/html/">W3Schools HTML</a>

Relative URLs

Path relative to the current file — used for linking pages on the same website.

<!-- Link to a file in the same folder -->
<a href="about.html">About Us</a>

<!-- Link to a file in a subfolder -->
<a href="pages/contact.html">Contact</a>

<!-- Link to a file one level up -->
<a href="../index.html">Go Home</a>

Anchor / Fragment Links

Jump to a section on the same page using id.

<!-- Link that jumps to a section -->
<a href="#about">Jump to About</a>
<a href="#projects">Jump to Projects</a>

<!-- The target sections — must have matching id -->
<h2 id="about">About Me</h2>
<h2 id="projects">My Projects</h2>

Email Links

<a href="mailto:hello@example.com">Send Email</a>

<!-- Pre-fill subject and body -->
<a href="mailto:hello@example.com?subject=Inquiry&body=Hi there">
  Email with subject
</a>

Phone Links

<!-- Opens phone dialler on mobile -->
<a href="tel:+919876543210">Call +91 98765 43210</a>

Download Links

<!-- Triggers download instead of navigation -->
<a href="resume.pdf" download>Download Resume</a>

<!-- Custom download filename -->
<a href="report-2024.pdf" download="Annual-Report.pdf">Download Report</a>

5.3 Image as a Link

Wrap <img> inside <a> to make an image clickable.

<a href="https://example.com">
  <img src="logo.png" alt="Company Logo — go to homepage" width="200">
</a>

5.4 Navigation Bar Pattern

<nav>
  <a href="index.html">Home</a>
  <a href="about.html">About</a>
  <a href="portfolio.html">Portfolio</a>
  <a href="contact.html">Contact</a>
</nav>

Always Use <nav> for Navigation

Wrapping navigation links in <nav> is semantic HTML — screen readers and search engines identify it as the site's navigation section.

5.5 Link Best Practices

Good Link Habits

  • Write descriptive link text — not "click here" or "read more"
  • <a href="resume.pdf">Download my resume</a>
  • <a href="resume.pdf">Click here</a>
  • Always add alt text when an image is a link
  • Use rel="noopener noreferrer" with target="_blank"
  • Use relative URLs for internal links — easier to maintain

🚀 Recommended Projects

Project 1 — Multi-page Website

Build 3 HTML pages (Home, About, Contact) linked to each other using a <nav> bar. Each page should have a consistent navigation at the top.

Project 2 — Resource Hub Page

Create a categorised links page — educational websites, YouTube channels, tools. Use anchor tags with target="_blank" and rel="noopener noreferrer". Group links under <h2> headings and use fragment links in a table of contents at the top.

📌 Quick Recall

  • <a href="...">text</a> = hyperlink
  • target="_blank" = opens in new tab (add rel="noopener noreferrer")
  • href="#id" = jump to section on same page
  • href="mailto:..." = email link | href="tel:..." = phone link
  • download attribute = triggers file download
  • Always use descriptive link text — not "click here"

04 - Text Formatting & Content | Next → 06 - Lists



Chapter 6 — Lists

Learning Outcome

Display structured data using all three types of HTML lists, including nested lists.

05 - Links & Navigation | Next → 07 - Semantic HTML5

6.1 Unordered List <ul>

Used when order doesn't matter — items are equal in rank.

<ul>
  <li>HTML</li>
  <li>CSS</li>
  <li>JavaScript</li>
</ul>

Renders as:

  • HTML
  • CSS
  • JavaScript

Changing Bullet Style (CSS)

<ul style="list-style-type: square;">  <!-- ■ square bullets -->
<ul style="list-style-type: circle;">  <!-- ○ circle bullets -->
<ul style="list-style-type: none;">    <!-- no bullets (for nav menus) -->

6.2 Ordered List <ol>

Used when sequence matters — steps, rankings, instructions.

<ol>
  <li>Open VS Code</li>
  <li>Create a new file — save as index.html</li>
  <li>Type your HTML</li>
  <li>Open with Live Server</li>
</ol>

type Attribute — Numbering Style

start Attribute — Starting Number

<!-- Start numbering from 5 -->
<ol start="5">
  <li>Fifth item</li>
  <li>Sixth item</li>
</ol>

<!-- Start from C with uppercase letters -->
<ol type="A" start="3">
  <li>Option C</li>
  <li>Option D</li>
</ol>

<!-- Reversed list -->
<ol reversed>
  <li>Gold medal</li>
  <li>Silver medal</li>
  <li>Bronze medal</li>
</ol>

6.3 Description List <dl>

Used for term–definition pairs — glossaries, FAQs, dictionaries.

<dl>
  <dt>HTML</dt>
  <dd>HyperText Markup Language — the structure of web pages.</dd>

  <dt>CSS</dt>
  <dd>Cascading Style Sheets — controls styling and layout.</dd>

  <dt>JavaScript</dt>
  <dd>A programming language that adds interactivity.</dd>
</dl>

6.4 Nested Lists

Lists can be nested inside each other. Indent clearly for readability.

<ul>
  <li>Frontend Development
    <ul>
      <li>HTML</li>
      <li>CSS
        <ul>
          <li>Flexbox</li>
          <li>Grid</li>
        </ul>
      </li>
      <li>JavaScript</li>
    </ul>
  </li>
  <li>Backend Development
    <ul>
      <li>Node.js</li>
      <li>Python</li>
    </ul>
  </li>
</ul>

Mixed nesting (ol inside ul):

<ul>
  <li>Step 1: Setup
    <ol>
      <li>Install VS Code</li>
      <li>Install Live Server extension</li>
    </ol>
  </li>
  <li>Step 2: Create Files</li>
</ul>

Nesting Rule

The nested <ul> or <ol> goes inside the <li> — not after it. ✅ <li>Item <ul>...</ul></li><li>Item</li><ul>...</ul>

6.5 Which List Type to Use?

🚀 Recommended Projects

Project 1 — Recipe Page

Build a complete cooking recipe page with:

  • <ol> for cooking steps (order matters)
  • <ul> for ingredients
  • <dl> for nutrition facts (term = nutrient name, dd = value)

Project 2 — Top 10 List Page

Create a "Top 10 Movies / Books / Games" page using:

  • <ol> for the ranked list
  • Nested <ul> inside each <li> for details (release year, genre, director)

📌 Quick Recall

  • <ul> = unordered (bullets) — for items without sequence
  • <ol> = ordered (numbers) — for steps, rankings
  • <li> = list item — goes inside <ul> or <ol>
  • <dl> = description list | <dt> = term | <dd> = definition
  • Nested lists: put <ul>/<ol> inside the <li>, not after it
  • ol type="A" = A,B,C | type="I" = Roman numerals | start="5" = begin at 5

05 - Links & Navigation | Next → 07 - Semantic HTML5

Chapter 7 — Semantic HTML5

Learning Outcome

Build meaningful, SEO-friendly page layouts using HTML5 semantic elements instead of generic <div> soup.

06 - Lists | Next → 08 - Images & Media

7.1 What is Semantic HTML?

Semantic HTML uses tags that describe their meaning and purpose, not just their visual appearance.


Why Semantic HTML Matters

4 Key Benefits

  1. Accessibility — Screen readers navigate by landmarks (<nav>, <main>) and announce element roles to blind users
  2. SEO — Search engines understand content hierarchy and index it correctly
  3. Readability — Other developers understand your code structure at a glance
  4. Maintainability — Easier to update, debug, and style

7.2 Page Layout Semantic Tags

<!DOCTYPE html>
<html lang="en">
<body>

  <header>
    <!-- Site logo, name, main navigation -->
  </header>

  <nav>
    <!-- Primary navigation links -->
  </nav>

  <main>
    <!-- The unique main content of this page (one per page) -->

    <section>
      <!-- A themed grouping of content -->
    </section>

    <article>
      <!-- Self-contained content: blog post, news article -->
    </article>

    <aside>
      <!-- Sidebar: related links, ads, author bio -->
    </aside>

  </main>

  <footer>
    <!-- Copyright, social links, contact info -->
  </footer>

</body>
</html>

7.3 Semantic Tags — Detailed Reference

<header>

Top of the page or a section. Contains logo, site title, or primary nav.

<header>
  <h1>My Portfolio</h1>
  <nav>...</nav>
</header>

<nav>

Navigation links — internal or external. Should contain <a> tags or a <ul> of links.

<nav>
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/about">About</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

<main>

The dominant content of the <body>. Use only once per page. Skip links target this.

<main id="main-content">
  <!-- Everything important goes here -->
</main>

<section>

A thematic grouping of content with its own heading. Use when content forms a distinct part of the page.

<section>
  <h2>About Us</h2>
  <p>We are a design studio...</p>
</section>

<article>

Self-contained, independently distributable content. Would still make sense if copied elsewhere.

<article>
  <h2>How to Learn HTML in 4 Weeks</h2>
  <time datetime="2025-04-24">April 24, 2025</time>
  <p>Start with the basics...</p>
</article>

<aside>

Content tangentially related to the main content — sidebars, pull quotes, ad panels.

<aside>
  <h3>Related Articles</h3>
  <ul>
    <li><a href="#">CSS Basics</a></li>
  </ul>
</aside>

<footer>

Bottom of page or section — copyright, links, contact info.

<footer>
  <p>&copy; 2025 My Website. All rights reserved.</p>
  <a href="/privacy">Privacy Policy</a>
</footer>

<figure> and <figcaption>

Used for images, diagrams, code blocks with a caption.

<figure>
  <img src="chart.png" alt="Sales grew 40% in Q4">
  <figcaption>Figure 1: Q4 2024 Sales Growth</figcaption>
</figure>

<time>

Machine-readable date/time. datetime attribute provides the standardised format.

<p>Published on <time datetime="2025-04-24">April 24, 2025</time></p>
<p>Class starts at <time datetime="09:00">9:00 AM</time></p>

<address>

Contact information for the nearest <article> or <body>.

<address>
  Written by <a href="mailto:arjun@example.com">Arjun Kumar</a><br>
  Trivandrum, Kerala, India
</address>

7.4 <article> vs <section>

The "Would it make sense alone?" Test

  • <article> — remove it from the page and it still makes sense? Use <article>. (A blog post, a news story, a product review)
  • <section> — it's part of a whole, needs context? Use <section>. (An "About Us" section, a "Skills" section of a portfolio)

7.5 Full Semantic Page Template

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>News Blog</title>
</head>
<body>

  <header>
    <h1>The Daily HTML</h1>
    <nav>
      <a href="/">Home</a>
      <a href="/tech">Tech</a>
      <a href="/about">About</a>
    </nav>
  </header>

  <main>

    <section id="featured">
      <h2>Featured Articles</h2>

      <article>
        <h3>HTML5 Turns 10</h3>
        <time datetime="2025-04-24">April 24, 2025</time>
        <p>A decade of semantic web...</p>
      </article>

      <article>
        <h3>Why Accessibility Matters</h3>
        <time datetime="2025-04-20">April 20, 2025</time>
        <p>Over 1 billion people have disabilities...</p>
      </article>

    </section>

    <aside>
      <h2>Trending Topics</h2>
      <ul>
        <li><a href="#">CSS Grid</a></li>
        <li><a href="#">Web Performance</a></li>
      </ul>
    </aside>

  </main>

  <footer>
    <address>
      Contact: <a href="mailto:editor@dailyhtml.com">editor@dailyhtml.com</a>
    </address>
    <p>&copy; 2025 The Daily HTML</p>
  </footer>

</body>
</html>

🚀 Recommended Projects

Project 1 — News Website Layout

Build a semantic news homepage with:

  • <header> with site title + <nav>
  • <main> containing 3 <article> cards
  • <aside> with trending topics
  • <footer> with copyright and contact

Project 2 — Div-to-Semantic Refactor

Take this div-heavy code and rewrite it semantically:

<div class="header"><div class="logo">...</div></div>
<div class="nav">...</div>
<div class="content"><div class="post">...</div></div>
<div class="sidebar">...</div>
<div class="footer">...</div>

📌 Quick Recall

  • Semantic = tags that describe their meaning, not just their look
  • <header> = top | <nav> = navigation | <main> = main content (once per page)
  • <section> = themed group | <article> = standalone content | <aside> = sidebar
  • <footer> = bottom | <figure> + <figcaption> = image with caption
  • <time datetime="..."> = machine-readable date
  • Article test: "Would it make sense alone?" → yes = <article>, no = <section>


Chapter 8 — Images & Media

Learning Outcome

Add and control images, audio, and video in web pages using HTML5 media elements.

07 - Semantic HTML5 | Next → 09 - Tables

8.1 The <img> Tag

<img> embeds an image. It is a self-closing void element — no closing tag.

<img src="photo.jpg" alt="A sunset over the mountains">

Required Attributes

alt is NOT Optional

alt text is read by screen readers for blind users, shown when image fails to load, and indexed by search engines. An empty alt="" is acceptable only for purely decorative images.

Optional Attributes

<img
  src="photo.jpg"
  alt="Students learning HTML in a classroom"
  width="600"
  height="400"
  loading="lazy"
  title="HTML Workshop 2025"
>

Always Set width and height

Setting width and height in HTML (or CSS) prevents Cumulative Layout Shift (CLS) — where content jumps around while images load. Google PageSpeed penalises CLS.

8.2 Image Paths

<!-- Same folder -->
<img src="photo.jpg" alt="...">

<!-- Subfolder -->
<img src="images/photo.jpg" alt="...">

<!-- Go up one level -->
<img src="../images/photo.jpg" alt="...">

<!-- Absolute URL (external image) -->
<img src="https://example.com/images/photo.jpg" alt="...">

8.3 Image Formats — When to Use What


Use WebP for Performance

Convert your images to WebP before uploading. Same visual quality, 25–35% smaller file size than JPEG.

8.4 <figure> and <figcaption>

Wrap images with captions in <figure> for semantic HTML.

<figure>
  <img src="cat.jpg" alt="An orange tabby cat sitting on a windowsill">
  <figcaption>Whiskers enjoying the afternoon sun.</figcaption>
</figure>

<figure> is Not Just for Images

<figure> can wrap code blocks, charts, diagrams, or any content that has a caption.

8.5 Responsive Images with srcset

Provide multiple image sizes — browser picks the best one for the screen.

<img
  src="photo-800.jpg"
  srcset="photo-400.jpg 400w,
          photo-800.jpg 800w,
          photo-1200.jpg 1200w"
  sizes="(max-width: 600px) 400px,
         (max-width: 1000px) 800px,
         1200px"
  alt="Responsive landscape photo"
>

8.6 HTML5 Audio — <audio>

<audio controls>
  <source src="song.mp3" type="audio/mpeg">
  <source src="song.ogg" type="audio/ogg">
  Your browser does not support the audio element.
</audio>

<!-- Autoplay only works with muted in most browsers -->
<audio autoplay muted loop>
  <source src="background.mp3" type="audio/mpeg">
</audio>

8.7 HTML5 Video — <video>

<video controls width="640" height="360" poster="thumbnail.jpg">
  <source src="video.mp4" type="video/mp4">
  <source src="video.webm" type="video/webm">
  Your browser does not support the video element.
</video>

Video Attributes

Multiple <source> Tags

Browsers don't all support the same formats. Provide fallbacks:

<video controls>
  <source src="clip.mp4" type="video/mp4">   <!-- Chrome, Edge, Safari -->
  <source src="clip.webm" type="video/webm"> <!-- Firefox fallback -->
  <!-- Text shown if browser supports neither -->
  Your browser does not support HTML5 video.
</video>

8.8 Embedding External Videos

Use <iframe> to embed YouTube or Vimeo videos:

<!-- YouTube embed -->
<iframe
  width="560"
  height="315"
  src="https://www.youtube.com/embed/VIDEO_ID"
  title="YouTube video player"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media"
  allowfullscreen>
</iframe>

🚀 Recommended Projects

Project 1 — Photo Gallery Page

Create a gallery with 6+ images using <figure> and <figcaption> for each.

  • Write descriptive alt text for every image
  • Use loading="lazy" on all images
  • Organise into 2 sections with <section> tags

Project 2 — Media Showcase Page

Build a page featuring:

  • An <audio> player with controls
  • A <video> player with a poster image
  • An embedded YouTube video with <iframe>
  • All wrapped in semantic <figure> elements with captions

📌 Quick Recall

  • <img src="..." alt="..."> = image (void element, no closing tag)
  • alt is required — empty alt="" only for decorative images
  • loading="lazy" = performance boost for below-fold images
  • JPEG = photos | PNG = transparency | SVG = scalable vector | WebP = modern best
  • <audio controls> + <source> = audio player
  • <video controls poster="..."> + <source> = video player
  • Always provide multiple <source> formats as browser fallbacks

07 - Semantic HTML5 | Next → 09 - Tables

Chapter 9 — Tables

Learning Outcome

Display structured data in tables, including merged cells with colspan and rowspan.

08 - Images & Media | Next → 10 - Forms & User Input

9.1 When to Use Tables

Use Tables For

  • Tabular data: schedules, timetables, price comparisons, mark sheets
  • Data with rows AND columns that relate to each other

Don't Use Tables For

  • Page layout (use CSS Flexbox or Grid instead)
  • Navigation menus
  • This was common in the 1990s — it is bad practice today

9.2 Basic Table Structure

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Subject</th>
      <th>Score</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Arjun</td>
      <td>HTML</td>
      <td>95</td>
    </tr>
    <tr>
      <td>Priya</td>
      <td>CSS</td>
      <td>88</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="2">Class Average</td>
      <td>91.5</td>
    </tr>
  </tfoot>
</table>

Table Tags Reference

<thead>, <tbody>, <tfoot> are Optional but Recommended

They make the table semantically meaningful and allow CSS to style header/body/footer separately. Screen readers also use them to describe the table structure.

9.3 Table Caption

<table>
  <caption>Student Results — Term 2, 2025</caption>
  <thead>...</thead>
  <tbody>...</tbody>
</table>

9.4 Merging Cells

colspan — Merge Horizontally (across columns)

<table border="1">
  <tr>
    <th colspan="3">Student Full Information</th>
    <!-- This header spans 3 columns -->
  </tr>
  <tr>
    <td>First Name</td>
    <td>Last Name</td>
    <td>Age</td>
  </tr>
</table>

rowspan — Merge Vertically (across rows)

<table border="1">
  <tr>
    <td rowspan="2">Monday</td>  <!-- spans 2 rows -->
    <td>9:00 AM — HTML Class</td>
  </tr>
  <tr>
    <!-- No <td> for "Monday" column — rowspan covers it -->
    <td>10:00 AM — CSS Class</td>
  </tr>
</table>

Remove the Extra Cell!

When you use rowspan="2", the cell fills 2 rows — remove the <td> from the second row for that column. If you don't, the table layout breaks.

Combined colspan + rowspan Example

<table border="1">
  <caption>Weekly Timetable</caption>
  <thead>
    <tr>
      <th>Day</th>
      <th>Period 1</th>
      <th>Period 2</th>
      <th>Period 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Monday</td>
      <td>HTML</td>
      <td colspan="2">Lab Session</td>  <!-- spans 2 periods -->
    </tr>
    <tr>
      <td rowspan="2">Tuesday</td>  <!-- spans Tuesday + Wednesday -->
      <td>CSS</td>
      <td>JavaScript</td>
      <td>Project Work</td>
    </tr>
    <tr>
      <!-- rowspan covers Tuesday cell -->
      <td>Review</td>
      <td>Quiz</td>
      <td>CSS Advanced</td>
    </tr>
  </tbody>
</table>

9.5 Accessibility in Tables

<!-- scope attribute: tells screen readers what the header applies to -->
<thead>
  <tr>
    <th scope="col">Name</th>    <!-- column header -->
    <th scope="col">Score</th>
  </tr>
</thead>
<tbody>
  <tr>
    <th scope="row">Arjun</th>  <!-- row header -->
    <td>95</td>
  </tr>
</tbody>

9.6 Complete Example — Mark Sheet

<table border="1" cellpadding="8" cellspacing="0">
  <caption>Class 10 — Final Examination Results 2025</caption>
  <thead>
    <tr>
      <th scope="col">Student</th>
      <th scope="col">Maths</th>
      <th scope="col">Science</th>
      <th scope="col">English</th>
      <th scope="col">Total</th>
      <th scope="col">Grade</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Arjun Kumar</th>
      <td>92</td>
      <td>88</td>
      <td>85</td>
      <td>265</td>
      <td>A+</td>
    </tr>
    <tr>
      <th scope="row">Priya Nair</th>
      <td>78</td>
      <td>82</td>
      <td>90</td>
      <td>250</td>
      <td>A</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="4">Class Average</td>
      <td>257.5</td>
      <td>A</td>
    </tr>
  </tfoot>
</table>

🚀 Recommended Projects

Project 1 — Student Mark Sheet

Create a marks table for 5 students across 5 subjects.

  • Use <thead>, <tbody>, <tfoot>
  • Use colspan for the totals footer row
  • Add a <caption> title
  • Include a "Grade" column

Project 2 — Weekly School Timetable

Build a full school timetable (Mon–Fri, 8 periods/day).

  • Use rowspan for lunch break spanning all days
  • Use colspan for lab sessions spanning 2 periods
  • Use <th scope="col"> for day headers and <th scope="row"> for period numbers

📌 Quick Recall

  • <table><thead> + <tbody> + <tfoot><tr><th> / <td>
  • <th> = header cell (bold, centered) | <td> = data cell
  • colspan="2" = cell spans 2 columns (horizontal merge)
  • rowspan="2" = cell spans 2 rows (vertical merge) — remove the extra <td>!
  • <caption> = table title
  • Don't use tables for layout — only for tabular data

08 - Images & Media | Next → 10 - Forms & User Input

Chapter 10 — Forms & User Input

Learning Outcome

Create interactive forms with various input types, labels, and HTML5 validation.

09 - Tables | Next → 11 - Layout Basics

10.1 The <form> Tag

<form> is the container for all input elements. It defines where and how the data is sent.

<form action="/submit" method="POST">
  <!-- form elements go here -->
  <button type="submit">Submit</button>
</form>

Key Attributes

GET vs POST


Always Use POST for Sensitive Data

Passwords, emails, and personal data must use method="POST". With GET, data appears in the URL and browser history.

10.2 The <input> Tag — All Types

<input> is a void (self-closing) element. The type attribute determines its behaviour.

<!-- Text types -->
<input type="text">
<input type="email">
<input type="password">
<input type="number">
<input type="tel">
<input type="url">
<input type="search">

<!-- Date/Time types -->
<input type="date">
<input type="time">
<input type="datetime-local">
<input type="month">
<input type="week">

<!-- Selection types -->
<input type="checkbox">
<input type="radio">
<input type="range">
<input type="color">

<!-- File & Hidden -->
<input type="file">
<input type="hidden">

<!-- Button types -->
<input type="submit">
<input type="reset">
<input type="button">


10.3 <label> — Accessible Form Labels

Always link labels to inputs using for + id. Clicking the label focuses the input.

<!-- Method 1: for/id pairing (recommended) -->
<label for="username">Username:</label>
<input type="text" id="username" name="username">

<!-- Method 2: wrapping (implicit label) -->
<label>
  Username:
  <input type="text" name="username">
</label>

Why Labels Matter

  • Clicking the label text focuses the input — larger click target on mobile
  • Screen readers announce the label when the input is focused
  • Without labels, form inputs are inaccessible to blind users

10.4 Radio Buttons & Checkboxes

<!-- Radio: choose ONE from a group — same name attribute -->
<p>Gender:</p>
<input type="radio" id="male" name="gender" value="male">
<label for="male">Male</label>

<input type="radio" id="female" name="gender" value="female">
<label for="female">Female</label>

<input type="radio" id="other" name="gender" value="other">
<label for="other">Other</label>

<!-- Checkbox: choose MULTIPLE — can be independently ticked -->
<p>Skills:</p>
<input type="checkbox" id="html" name="skills" value="html" checked>
<label for="html">HTML</label>

<input type="checkbox" id="css" name="skills" value="css">
<label for="css">CSS</label>

<input type="checkbox" id="js" name="skills" value="js">
<label for="js">JavaScript</label>

Radio vs Checkbox

  • Radio — grouped by the same name. Selecting one deselects others.
  • Checkbox — each is independent. Can check as many as you want.

10.5 Textarea & Select

<!-- Multi-line text input -->
<label for="message">Message:</label>
<textarea id="message" name="message" rows="5" cols="40"
  placeholder="Write your message here..."
  maxlength="500"></textarea>

<!-- Dropdown select -->
<label for="course">Course:</label>
<select id="course" name="course">
  <option value="">-- Choose a course --</option>
  <optgroup label="Web Development">
    <option value="html">HTML & CSS</option>
    <option value="js">JavaScript</option>
    <option value="react" selected>React</option>
  </optgroup>
  <optgroup label="Backend">
    <option value="node">Node.js</option>
    <option value="python">Python</option>
  </optgroup>
</select>

<!-- Multi-select (hold Ctrl/Cmd to pick multiple) -->
<select name="languages" multiple size="4">
  <option value="html">HTML</option>
  <option value="css">CSS</option>
  <option value="js">JavaScript</option>
  <option value="python">Python</option>
</select>

10.6 Grouping with <fieldset> and <legend>

<form>
  <fieldset>
    <legend>Personal Information</legend>
    <label for="fname">First Name:</label>
    <input type="text" id="fname" name="fname" required>
    <label for="lname">Last Name:</label>
    <input type="text" id="lname" name="lname" required>
  </fieldset>

  <fieldset>
    <legend>Account Details</legend>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>
    <label for="pass">Password:</label>
    <input type="password" id="pass" name="pass" required>
  </fieldset>
</form>

10.7 HTML5 Form Validation

Built-in validation — no JavaScript needed.

<form>
  <!-- Required field -->
  <input type="text" name="name" required placeholder="Full name">

  <!-- Email format validation -->
  <input type="email" name="email" required placeholder="example@email.com">

  <!-- Number range -->
  <input type="number" name="age" min="18" max="100" required>

  <!-- Text length -->
  <input type="text" name="username" minlength="3" maxlength="20" required>

  <!-- Pattern (regex) validation -->
  <input type="text" name="postcode"
    pattern="[0-9]{6}"
    title="6-digit PIN code"
    placeholder="PIN Code">

  <!-- Strong password (uppercase + lowercase + digit + 8 chars) -->
  <input type="password" name="password"
    pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
    title="Must be 8+ chars with uppercase, lowercase, and number"
    required>

  <button type="submit">Register</button>
  <button type="reset">Clear</button>
</form>

Validation Attributes Summary

10.8 Full Registration Form Example

<form action="/register" method="POST" enctype="multipart/form-data">
  <fieldset>
    <legend>Personal Details</legend>

    <label for="name">Full Name *</label>
    <input type="text" id="name" name="name" required
      minlength="3" maxlength="50" placeholder="Arjun Kumar">

    <label for="email">Email *</label>
    <input type="email" id="email" name="email" required placeholder="arjun@example.com">

    <label for="dob">Date of Birth *</label>
    <input type="date" id="dob" name="dob" required max="2007-12-31">

    <p>Gender *</p>
    <input type="radio" id="male" name="gender" value="male" required>
    <label for="male">Male</label>
    <input type="radio" id="female" name="gender" value="female">
    <label for="female">Female</label>
  </fieldset>

  <fieldset>
    <legend>Account Setup</legend>

    <label for="password">Password *</label>
    <input type="password" id="password" name="password"
      required minlength="8"
      pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
      title="8+ chars with uppercase, lowercase, and number">

    <label for="photo">Profile Photo</label>
    <input type="file" id="photo" name="photo" accept="image/*">
  </fieldset>

  <input type="checkbox" id="terms" name="terms" required>
  <label for="terms">I agree to the <a href="/terms">Terms & Conditions</a></label>

  <button type="submit">Create Account</button>
  <button type="reset">Reset Form</button>
</form>

🚀 Recommended Projects

Project 1 — Student Registration Form

Build a complete student registration form with:

  • Name, email, password (with pattern validation)
  • Date of birth (<input type="date">)
  • Gender (radio buttons)
  • Course selection (<select> with <optgroup>)
  • Profile photo upload (<input type="file">)
  • Terms checkbox
  • Submit and Reset buttons
  • Use <fieldset> to group sections

Project 2 — Job Application Form

Create a job application with sections grouped by <fieldset>:

  • Personal info (name, email, phone, address)
  • Education (degree select, year, percentage)
  • Skills (checkboxes for multiple skills)
  • Cover letter (<textarea>)
  • Resume upload (<input type="file" accept=".pdf">)

📌 Quick Recall

  • <form action="..." method="POST"> = container, defines submit destination
  • GET = data in URL (search) | POST = hidden (login, register)
  • <input type="..."> = void element, type determines behaviour
  • name attribute = required for form submission (the data key)
  • <label for="id"> = always link labels to inputs (accessibility!)
  • Radio = same name, pick one | Checkbox = independent, pick many
  • <select> + <option> + <optgroup> = dropdown
  • <textarea> = multi-line text
  • <fieldset> + <legend> = group related fields
  • required, min, max, pattern, minlength = HTML5 validation

09 - Tables | Next → 11 - Layout Basics


Chapter 11 — Layout Basics

Learning Outcome

Understand block vs inline elements, and use <div> and <span> to structure and style content.

10 - Forms & User Input | Next → 12 - CSS JS Integration & Accessibility

11.1 Block vs Inline Elements

This is one of the most fundamental concepts in HTML layout.

Block-Level Elements

  • Start on a new line
  • Take up the full width available (by default)
  • Can have width, height, margin, padding applied
  • Stack vertically
<div>Block 1</div>
<div>Block 2</div>
<div>Block 3</div>
<!-- Each starts on its own line -->

Common block elements: <div>, <p>, <h1><h6>, <ul>, <ol>, <li>, <table>, <form>, <header>, <nav>, <main>, <section>, <article>, <aside>, <footer>, <blockquote>, <pre>, <hr>

Inline Elements

  • Flow within text — no line break
  • Width/height = determined by content (can't set with CSS by default)
  • Sit side by side in the same line
<p>
  I love <strong>HTML</strong> and <em>CSS</em> and
  <a href="#">web development</a>.
</p>
<!-- All flow within the same paragraph line -->

Common inline elements: <span>, <a>, <strong>, <em>, <mark>, <code>, <img>, <input>, <label>, <button>, <abbr>, <sub>, <sup>, <br>

Inline-Block

Behaves inline (no line break) but accepts width and height. <img> and <input> are naturally inline-block. You can make any element inline-block with CSS: display: inline-block;


11.2 Quick Comparison Table


11.3 <div> — The Block Container

<div> (division) is a generic block-level container with no visual style and no semantic meaning on its own.

Use <div> when:

  • No semantic tag fits the purpose
  • You need to group elements for CSS/JS targeting
  • Creating layout sections that will be styled with CSS
<!-- Grouping for CSS styling -->
<div class="card">
  <div class="card-header">
    <h2>Product Name</h2>
    <span class="badge">New</span>
  </div>
  <div class="card-body">
    <p>Product description here.</p>
    <p class="price">₹999</p>
  </div>
  <div class="card-footer">
    <button>Add to Cart</button>
  </div>
</div>

Semantic First, div Second

Before reaching for <div>, ask: "Is there a semantic tag for this?"

  • Navigation? → <nav>
  • Article? → <article>
  • Page section? → <section>
  • Top of page? → <header> Only use <div> when none of the above fit.

11.4 <span> — The Inline Container

<span> is a generic inline element — it wraps part of text within a line without breaking flow.

Use <span> when:

  • You want to style or target part of text within a paragraph
  • No semantic inline tag fits (like <strong>, <em>, <mark>)
<!-- Style part of a sentence -->
<p>
  The price is <span style="color: red; font-weight: bold;">₹499</span> only.
</p>

<!-- Target text with a class for JS -->
<p>
  Your score: <span class="score" id="score-value">87</span>/100
</p>

<!-- Multiple uses in one paragraph -->
<p>
  Temperature: <span class="temp hot">42°C</span> in
  <span class="city">Chennai</span> today.
</p>

11.5 <div> vs <span> — Side by Side

<!-- div: wraps a BLOCK of content -->
<div class="alert-box">
  <strong>Warning:</strong> This action cannot be undone.
</div>

<!-- span: wraps a WORD or PHRASE within text -->
<p>
  This action <span class="danger-text">cannot be undone</span>.
</p>

11.6 Nesting Rules

Block elements can contain both block and inline elements. Inline elements should only contain inline elements — not block elements.

<!-- ✅ Correct: block contains block and inline -->
<div>
  <h2>Title</h2>
  <p>Some <strong>bold</strong> text.</p>
</div>

<!-- ✅ Correct: inline contains inline -->
<p>Text with <a href="#"><strong>bold link</strong></a>.</p>

<!-- ❌ Wrong: inline element containing block element -->
<span>
  <div>This is invalid HTML</div>
</span>

<!-- ❌ Wrong: inline inside inline that can't nest -->
<a href="#">Click <a href="#">nested link</a></a>

🚀 Recommended Projects

Project 1 — Product Card Layout

Create 3 product cards using <div> containers. Each card should contain:

  • <img> for product image
  • <h3> product name
  • <p> with <span class="price"> for price
  • <button> Buy Now All 3 cards side by side using display: flex in CSS.

Project 2 — Magazine-style Layout

Build a two-column page layout using <div> containers:

  • Left <div> (width 70%) for main article
  • Right <div> (width 30%) for sidebar
  • Use <span> to highlight key terms in the article text

📌 Quick Recall

  • Block = new line, full width (<div>, <p>, <h1>) — stacks vertically
  • Inline = flows in text, content-width (<span>, <a>, <strong>) — sits side by side
  • Inline-block = inline flow but accepts dimensions (<img>, <input>)
  • <div> = block container — group elements for layout/styling
  • <span> = inline container — style part of text without line break
  • Inline elements must not contain block elements
  • Prefer semantic tags (<header>, <nav>, <section>) over <div> when possible

10 - Forms & User Input | Next → 12 - CSS JS Integration & Accessibility

Chapter 12 — CSS & JS Integration & Accessibility

Learning Outcome

Connect HTML with CSS and JavaScript, and build accessible web pages using ARIA and best practices.

11 - Layout Basics | Back to → 00 - HTML Tutorial MOC

12.1 Three Ways to Add CSS

Method 1: Inline CSS

<p style="color: blue; font-size: 18px; font-weight: bold;">Hello</p>
  • Highest specificity — overrides everything
  • Hard to maintain, not reusable
  • Use only for truly one-off, quick tweaks

Method 2: Internal CSS (<style> tag)

<head>
  <style>
    p { color: blue; }
    h1 { font-size: 2rem; }
    .highlight { background: yellow; }
  </style>
</head>
  • Good for single-page projects or email templates
  • Keeps styles and HTML in one file

Method 3: External CSS (Best Practice ✅)

<head>
  <link rel="stylesheet" href="styles.css">
</head>
/* styles.css */
p { color: blue; }
h1 { font-size: 2rem; }
  • Separate file — clean separation of concerns
  • One CSS file styles many pages — efficient
  • Browser caches the CSS file — faster page loads

Which Method to Use?

  • Small experiments / learning → internal <style>
  • Any real project → external CSS file always
  • Never use inline style for layout — only micro-overrides

12.2 Three Ways to Add JavaScript

Method 1: Inline JS (Avoid ❌)

<button onclick="alert('Hello!')">Click</button>

Method 2: Internal JS (<script> tag)

<body>
  <h1>Hello</h1>

  <!-- JS at the bottom of body — HTML loads first -->
  <script>
    document.querySelector('h1').style.color = 'red';
  </script>
</body>

Method 3: External JS (Best Practice ✅)

<head>
  <!-- defer: loads JS after HTML is parsed (recommended) -->
  <script src="app.js" defer></script>
</head>

defer vs async

defer async When downloaded Parallel with HTML Parallel with HTML When executed After HTML parsed As soon as downloaded Order preserved ✅ Yes ❌ No Use for Most scripts Independent scripts (analytics) Always Use defer

<script src="app.js" defer> is the modern best practice. It downloads in the background and runs after HTML is ready — no blocking, no timing issues.

12.3 Accessibility Fundamentals

Accessibility (a11y) means making your website usable by everyone — including people with visual, motor, or cognitive disabilities.

Why Accessibility Matters

  • 1 in 6 people worldwide have a disability (WHO)
  • Accessible sites rank better in Google
  • Many countries have legal requirements for accessibility
  • Good accessibility improves UX for everyone (captions help in noisy environments too)

12.4 Core Accessibility Practices

1. Alt Text on Images

<!-- ✅ Descriptive alt text -->
<img src="chart.png" alt="Bar chart showing 40% sales growth in Q4 2024">

<!-- ✅ Decorative image — empty alt (screen reader skips it) -->
<img src="divider-line.svg" alt="">

<!-- ❌ Useless alt text -->
<img src="chart.png" alt="image">
<img src="chart.png" alt="chart.png">

2. Label Every Input

<!-- ✅ Accessible -->
<label for="email">Email Address</label>
<input type="email" id="email" name="email">

<!-- ❌ Not accessible — no label -->
<input type="email" name="email" placeholder="Email">

3. Logical Heading Hierarchy

<!-- ✅ Correct hierarchy -->
<h1>Main Title (once per page)</h1>
  <h2>Section</h2>
    <h3>Sub-section</h3>
    <h3>Another Sub-section</h3>
  <h2>Another Section</h2>

<!-- ❌ Skipping levels -->
<h1>Main Title</h1>
<h4>Why did we skip h2 and h3?</h4>

4. Keyboard Navigation

All interactive elements must be usable with Tab key only — no mouse required.

<!-- tabindex="0" makes non-interactive elements focusable -->
<div tabindex="0" role="button">Custom Button</div>

<!-- tabindex="-1" removes from tab order (JS controlled) -->
<div tabindex="-1">Only focusable via JS</div>

<!-- Skip navigation link (first thing on page) -->
<a href="#main-content" class="skip-link">Skip to main content</a>
...
<main id="main-content">...</main>

12.5 ARIA Attributes

ARIA = Accessible Rich Internet Applications. Adds accessibility semantics to HTML.

<!-- aria-label: text label for screen readers (no visible text) -->
<button aria-label="Close dialog">
  <svg><!-- X icon --></svg>
</button>

<!-- aria-hidden: hide decorative elements from screen readers -->
<span aria-hidden="true">★★★★☆</span>
<span class="sr-only">4 out of 5 stars</span>

<!-- aria-expanded: toggle state for accordions/dropdowns -->
<button aria-expanded="false" aria-controls="menu">
  Menu
</button>
<ul id="menu" hidden>...</ul>

<!-- aria-live: announce dynamic content changes -->
<div aria-live="polite" id="status">
  <!-- Changes here are announced by screen readers -->
</div>

<!-- role: define element purpose -->
<div role="alert">Form submitted successfully!</div>
<div role="navigation">...</div>
<div role="search">...</div>

Common ARIA Attributes


First Rule of ARIA

"No ARIA is better than bad ARIA." If you can use a native HTML element instead, do that. <button> is better than <div role="button">. <nav> is better than <div role="navigation">.

12.6 Screen Reader Only Text

Sometimes you need text for screen readers but not visible on screen.

<style>
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
  }
</style>

<!-- Visible icon, hidden text for screen reader -->
<button>
  <svg aria-hidden="true"><!-- cart icon --></svg>
  <span class="sr-only">Add to cart</span>
</button>

12.7 Colour Contrast & Focus Indicators

<!-- Always ensure visible focus ring -->
<style>
  /* Never do this — removes accessibility -->
  /* :focus { outline: none; } */

  /* Do this instead — custom but visible focus -->
  :focus {
    outline: 3px solid #005fcc;
    outline-offset: 2px;
  }
</style>

WCAG Contrast Ratios

  • Normal text: minimum 4.5:1 contrast ratio
  • Large text (18px+ or 14px bold): minimum 3:1
  • Check with tools: WebAIM Contrast Checker, browser DevTools

12.8 HTML Best Practices Checklist

Before You Ship a Page

  • <!DOCTYPE html> on line 1
  • lang="en" on <html>
  • charset="UTF-8" in <head>
  • viewport meta tag in <head>
  • Descriptive <title> tag
  • One <h1> per page, logical heading order
  • Every <img> has an alt attribute
  • Every <input> has a <label>
  • External CSS in <link>, external JS in <script defer>
  • Semantic tags used (<header>, <main>, <nav>, etc.)
  • Tab through the page — is it navigable by keyboard?
  • No passwords or secrets in HTML comments

🚀 Recommended Projects

Project 1 — Styled Portfolio with JavaScript

Link an external style.css and app.js to your portfolio page.

  • CSS: set font, colours, and a two-column layout
  • JS: add a dark mode toggle button using document.body.classList.toggle()
  • Ensure the button has aria-label and aria-pressed attributes

Project 2 — Accessible Contact Form

Build a fully accessible contact form:

  • Every input has a visible <label> linked by for/id
  • Icon-only buttons have aria-label
  • Use required on required fields
  • Add a success aria-live="polite" div that gets filled with "Form submitted!" via JS
  • Test the entire form using only the Tab key

📌 Quick Recall

  • Inline CSS → attribute style="" | Internal → <style> in head | External → <link> (best)
  • JS placement: <script src="app.js" defer> in <head> (preferred) or before </body>
  • defer = runs after HTML parses | async = runs as soon as downloaded
  • alt="" on decorative images | descriptive alt on meaningful images
  • Every <input> needs a <label for="..."> matching the input's id
  • ARIA: aria-label, aria-hidden, aria-expanded, role, aria-live
  • First Rule of ARIA: use native HTML elements first
  • Never remove :focus outline — keyboard users rely on it

11 - Layout Basics | Back to → 00 - HTML Tutorial MOC