~/hackweb.dev
HTML5 Elements
Quiz
...

HTML5 Elements

beginner · updated Tue Sep 08 2026Contribute

Master interactive elements like details, summary, dialog, and progress.

HTML5 Elements

HTML5 introduced interactive elements that work without JavaScript. They’re perfect for accordions, modals, and progress indicators.

Details and Summary

Create expandable content (accordion):

<details>
  <summary>Click to expand</summary>
  <p>This content is hidden by default.</p>
  <p>You can put any HTML here.</p>
</details>

With open attribute:

<details open>
  <summary>This starts expanded</summary>
  <p>Content visible by default</p>
</details>

Multiple accordions:

<details>
  <summary>Section 1</summary>
  <p>Content for section 1</p>
</details>

<details>
  <summary>Section 2</summary>
  <p>Content for section 2</p>
</details>

<details>
  <summary>Section 3</summary>
  <p>Content for section 3</p>
</details>

Dialog Element

Native modal dialogs:

<dialog id="myDialog">
  <h2>Confirm Action</h2>
  <p>Are you sure you want to proceed?</p>
  <button onclick="this.closest('dialog').close()">Cancel</button>
  <button onclick="handleConfirm()">Confirm</button>
</dialog>

<button onclick="document.getElementById('myDialog').showModal()">
  Open Dialog
</button>

Dialog methods:

  • showModal() — Opens as modal (with backdrop)
  • show() — Opens as non-modal
  • close() — Closes the dialog

Close on backdrop click:

<dialog id="myDialog">
  <p>Click outside to close</p>
</dialog>

<script>
  const dialog = document.getElementById('myDialog');
  dialog.addEventListener('click', (e) => {
    if (e.target === dialog) {
      dialog.close();
    }
  });
</script>

Progress Element

Shows completion progress:

<progress value="70" max="100">70%</progress>

Indeterminate progress:

<progress>Loading...</progress>

With JavaScript:

<progress id="progress" value="0" max="100"></progress>
<span id="progressText">0%</span>

<script>
  const progress = document.getElementById('progress');
  const text = document.getElementById('progressText');

  let value = 0;
  const interval = setInterval(() => {
    value += 10;
    progress.value = value;
    text.textContent = `${value}%`;
    if (value >= 100) clearInterval(interval);
  }, 500);
</script>

Meter Element

Shows a scalar value within a range:

<meter value="0.7">70%</meter>

With min/max:

<meter min="0" max="100" value="75">75 out of 100</meter>

With optimal/low/high:

<!-- Low value -->
<meter min="0" max="100" low="30" high="70" optimum="80" value="20">
  Low
</meter>

<!-- Optimal value -->
<meter min="0" max="100" low="30" high="70" optimum="80" value="80">
  Optimal
</meter>

<!-- High value -->
<meter min="0" max="100" low="30" high="70" optimum="80" value="95">
  High
</meter>

Use cases:

  • Disk space usage
  • Battery level
  • CPU usage
  • Score/rating

Output Element

Shows calculation results:

<form oninput="result.value = a.valueAsNumber + b.valueAsNumber">
  <input type="number" id="a" value="0" /> +
  <input type="number" id="b" value="0" /> =
  <output name="result" for="a b">0</output>
</form>

Complete Example

Here’s a complete page using HTML5 interactive elements:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>HTML5 Interactive Elements</title>
    <style>
      details {
        margin: 10px 0;
        padding: 10px;
        border: 1px solid #ddd;
        border-radius: 5px;
      }

      summary {
        cursor: pointer;
        font-weight: bold;
      }

      dialog {
        border: none;
        border-radius: 10px;
        padding: 20px;
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
      }

      dialog::backdrop {
        background: rgba(0, 0, 0, 0.5);
      }

      progress,
      meter {
        width: 200px;
        height: 20px;
      }
    </style>
  </head>
  <body>
    <h1>HTML5 Interactive Elements</h1>

    <!-- Accordion FAQ -->
    <section>
      <h2>FAQ</h2>

      <details>
        <summary>What is HTML5?</summary>
        <p>HTML5 is the latest version of HTML with new elements and APIs.</p>
      </details>

      <details>
        <summary>Do I need JavaScript for these?</summary>
        <p>No! Details, summary, and dialog work without JavaScript.</p>
      </details>

      <details>
        <summary>Are these elements accessible?</summary>
        <p>Yes, they have built-in keyboard support and ARIA roles.</p>
      </details>
    </section>

    <!-- Dialog -->
    <section>
      <h2>Dialog Example</h2>
      <button onclick="document.getElementById('confirmDialog').showModal()">
        Delete Account
      </button>

      <dialog id="confirmDialog">
        <h3>Confirm Deletion</h3>
        <p>This action cannot be undone. Are you sure?</p>
        <form method="dialog">
          <button value="cancel">Cancel</button>
          <button value="confirm">Delete</button>
        </form>
      </dialog>
    </section>

    <!-- Progress -->
    <section>
      <h2>File Upload Progress</h2>
      <progress id="uploadProgress" value="0" max="100"></progress>
      <span id="uploadPercent">0%</span>
    </section>

    <!-- Meter -->
    <section>
      <h2>Disk Usage</h2>
      <meter min="0" max="100" low="30" high="70" optimum="50" value="45">
        45%
      </meter>
      <span>45% used</span>
    </section>

    <!-- Calculator -->
    <section>
      <h2>Calculator</h2>
      <form oninput="calc.value = num1.valueAsNumber + num2.valueAsNumber">
        <input type="number" id="num1" value="0" /> +
        <input type="number" id="num2" value="0" /> =
        <output name="calc" for="num1 num2">0</output>
      </form>
    </section>

    <script>
      // Simulate upload progress
      const progress = document.getElementById('uploadProgress');
      const percent = document.getElementById('uploadPercent');
      let value = 0;

      setInterval(() => {
        if (value < 100) {
          value += 5;
          progress.value = value;
          percent.textContent = `${value}%`;
        }
      }, 300);
    </script>
  </body>
</html>

When to Use Each

Use <details> for:

  • FAQs
  • Expandable sections
  • Show/hide content
  • Progressive disclosure

Use <dialog> for:

  • Confirmations
  • Forms
  • Notifications
  • Modal content

Use <progress> for:

  • File uploads
  • Form completion
  • Loading states
  • Step indicators

Use <meter> for:

  • Disk usage
  • Battery level
  • CPU usage
  • Scores/ratings

Best Practices

  1. Always provide fallback — Text inside elements shows if unsupported
  2. Use form method=“dialog” — For dialog forms to close properly
  3. Style with CSS — Native elements are customizable
  4. Add keyboard support — Elements have it built-in
  5. Use semantic names — Summary should describe content

Common Mistakes

  1. Not using method=“dialog” — Form won’t close dialog
  2. Missing summary in details — Summary is required
  3. Using progress for unknown duration — Use indeterminate progress
  4. Using meter for exact values — Use number input instead
  5. Not styling dialogs — Native dialogs look plain without CSS