CPCODELAB
Practice

Practice HTML

You’ve read the lessons — now prove it. Take the quiz for instant feedback, then work the coding exercises. Try each one yourself before you reveal the solution.

Quick quiz

17 questions
Score: 0 / 17
0/17 answered
  1. 1

    Which tag is used to define the root of an HTML document?

  2. 2

    Which heading tag produces the largest text by default?

  3. 3

    What is the correct way to create a hyperlink to https://example.com?

  4. 4

    Which attribute on <img> is required for accessibility?

  5. 5

    Which HTML element is used for an unordered (bulleted) list?

  6. 6

    What does the <label> element's for attribute do in a form?

  7. 7

    Which input type should be used to collect an email address?

  8. 8

    Which element represents the main navigation links of a page?

  9. 9

    Where should <meta> tags be placed in an HTML document?

  10. 10

    Which of the following correctly defines a table row containing two header cells?

  11. 11

    Which semantic element should wrap the primary content unique to a page (excluding navbars, sidebars, and footers)?

  12. 12

    Which element lets the browser choose the best image source for the user's screen size or format support?

  13. 13

    What does the scope="row" attribute on a <th> cell tell the browser?

  14. 14

    Which HTML element provides a list of autocomplete suggestions for a text input without restricting the user to those options?

  15. 15

    In inline SVG, which attribute value makes a decorative icon invisible to screen readers?

  16. 16

    How do you read the value of data-product-id="42" in JavaScript?

  17. 17

    Which <meta> tag enables a rich social-media preview card (title, description, and image) when a link is shared?

🛠️

Coding exercises

8 tasks
1

Build a Basic HTML Page

Easy

Create a complete, valid HTML5 document that includes: a <!DOCTYPE html> declaration, a <head> with <meta charset>, a <title>, and a <body> containing an <h1> heading and one <p> paragraph.

Starter
html
<!DOCTYPE html>
<html lang="en">
</html>
💡 Show hint

The <head> element holds metadata; <body> holds visible content. Don't forget charset="UTF-8" on <meta>.

✅ Show solution
html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My First Page</title>
  </head>
  <body>
    <h1>Welcome to My Page</h1>
    <p>This is my first HTML document. It has a heading and a paragraph.</p>
  </body>
</html>
2

Links, Images, and Lists

Easy

Write an HTML snippet (no need for full document shell) that contains: 1. An <img> pointing to https://picsum.photos/200 with a meaningful alt attribute. 2. An <a> that opens https://example.com in a new tab. 3. An unordered list of three of your favourite programming languages.

💡 Show hint

To open a link in a new tab use target="_blank". Pair it with rel="noopener noreferrer" for security.

✅ Show solution
html
<img src="https://picsum.photos/200" alt="A random placeholder photo" />

<a href="https://example.com" target="_blank" rel="noopener noreferrer">Visit Example</a>

<ul>
  <li>JavaScript</li>
  <li>Python</li>
  <li>TypeScript</li>
</ul>
3

Accessible Contact Form

Medium

Build an HTML form with action="/contact" and method="post" that collects: Name (text), Email (email type), Message (textarea), and a submit button. Every input must have a properly associated <label> using for/id. The submit button text should read "Send Message".

💡 Show hint

Match each <label for="X"> with <input id="X">. Use <textarea> for multi-line text — it is not a self-closing tag.

✅ Show solution
html
<form action="/contact" method="post">
  <div>
    <label for="name">Name</label>
    <input type="text" id="name" name="name" required />
  </div>

  <div>
    <label for="email">Email</label>
    <input type="email" id="email" name="email" required />
  </div>

  <div>
    <label for="message">Message</label>
    <textarea id="message" name="message" rows="5"></textarea>
  </div>

  <button type="submit">Send Message</button>
</form>
4

Product Data Table

Medium

Create an HTML table that lists three products with columns: Product, Price, and In Stock. Use <thead> for header rows with <th> cells and <tbody> for data rows with <td> cells. Add a <caption> that reads "Available Products".

💡 Show hint

<caption> goes immediately after the opening <table> tag. Use scope="col" on <th> elements to improve screen-reader support.

✅ Show solution
html
<table>
  <caption>Available Products</caption>
  <thead>
    <tr>
      <th scope="col">Product</th>
      <th scope="col">Price</th>
      <th scope="col">In Stock</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Mechanical Keyboard</td>
      <td>$89.99</td>
      <td>Yes</td>
    </tr>
    <tr>
      <td>Wireless Mouse</td>
      <td>$34.99</td>
      <td>Yes</td>
    </tr>
    <tr>
      <td>USB-C Hub</td>
      <td>$49.99</td>
      <td>No</td>
    </tr>
  </tbody>
</table>
5

Semantic Blog Post Layout

Hard

Mark up a complete blog-post page using semantic HTML5 elements. The page must include: - A <header> with site name in an <h1> and a <nav> containing links to Home, Blog, and About. - A <main> containing one <article> with: an <h2> title, a <p> of body text, a <figure> with an <img> (with alt) and a <figcaption>. - An <aside> inside <main> with a short "About the Author" blurb. - A <footer> with a copyright notice. Wrap <article> and <aside> in a container <div> for layout purposes.

💡 Show hint

<article> should make sense on its own if taken out of context. <aside> holds content tangentially related to the main content. <figure> groups media with its caption.

✅ Show solution
html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My Blog</title>
  </head>
  <body>
    <header>
      <h1>Dev Diaries</h1>
      <nav aria-label="Primary navigation">
        <ul>
          <li><a href="/">Home</a></li>
          <li><a href="/blog">Blog</a></li>
          <li><a href="/about">About</a></li>
        </ul>
      </nav>
    </header>

    <main>
      <div class="content-wrapper">
        <article>
          <h2>Understanding Semantic HTML</h2>
          <p>Semantic HTML uses meaningful elements to describe content structure, making pages more accessible to screen readers and easier for search engines to index.</p>
          <figure>
            <img src="https://picsum.photos/600/300" alt="A diagram showing HTML semantic elements laid out on a page" />
            <figcaption>Fig 1 — Common semantic elements and their typical positions.</figcaption>
          </figure>
        </article>

        <aside aria-label="About the author">
          <h3>About the Author</h3>
          <p>Jane is a front-end developer with a passion for accessibility and clean markup.</p>
        </aside>
      </div>
    </main>

    <footer>
      <p>&copy; 2026 Dev Diaries. All rights reserved.</p>
    </footer>
  </body>
</html>
6

Responsive Picture Element

Medium

Write a <picture> element that serves: 1. /images/hero.avif to browsers that support AVIF. 2. /images/hero.webp to browsers that support WebP. 3. /images/hero.jpg as the fallback <img> with a meaningful alt, width="1200", and height="675".

💡 Show hint

List <source type="image/avif"> first, then <source type="image/webp">, then the <img> fallback. The <img> must always be the last child.

✅ Show solution
html
<picture>
  <source type="image/avif" srcset="/images/hero.avif" />
  <source type="image/webp" srcset="/images/hero.webp" />
  <img
    src="/images/hero.jpg"
    alt="A mountain landscape at golden hour"
    width="1200"
    height="675"
  />
</picture>
7

Accessible Data Table with colspan

Medium

Create a table showing quarterly scores for two students. Requirements: - <caption> reading "Student Scores — 2026". - A header row where a "Scores" <th> spans two columns (Q1 and Q2). - Row-header <th scope="row"> cells for each student name. - Use <thead>, <tbody>, and scope="col" on column headers.

💡 Show hint

The first header row has 2 cells (Name + Scores with colspan="2"). The second header row has 2 cells (Q1 + Q2) because Name already spans via rowspan="2" — or you can use two separate rows without rowspan.

✅ Show solution
html
<table>
  <caption>Student Scores &mdash; 2026</caption>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col" colspan="2">Scores</th>
    </tr>
    <tr>
      <th scope="col">Q1</th>
      <th scope="col">Q2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Alice</th>
      <td>88</td>
      <td>91</td>
    </tr>
    <tr>
      <th scope="row">Bob</th>
      <td>74</td>
      <td>80</td>
    </tr>
  </tbody>
</table>
8

Product Card with data-* and ARIA

Hard

Build a product card <article> for a "Wireless Headphones" product (id 101, price $59.99, in-stock). Requirements: - Store data-product-id, data-price, and data-in-stock on the <article>. - An <img> using /images/headphones.jpg with descriptive alt. - An <h2> for the product name. - A paragraph with the price wrapped in a <span> with aria-label="Price: $59.99" for screen-reader clarity. - An "Add to cart" <button> with type="button" and aria-label="Add Wireless Headphones to cart".

💡 Show hint

data-* attributes go on the opening tag. Use aria-label on the <span> and the <button>. The <article> element is correct here because the card is self-contained.

✅ Show solution
html
<article
  data-product-id="101"
  data-price="59.99"
  data-in-stock="true"
>
  <img
    src="/images/headphones.jpg"
    alt="Wireless over-ear headphones in matte black"
    width="300"
    height="300"
  />
  <h2>Wireless Headphones</h2>
  <p>
    <span aria-label="Price: $59.99">$59.99</span>
  </p>
  <button type="button" aria-label="Add Wireless Headphones to cart">
    Add to cart
  </button>
</article>