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-modalclose()— 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
- Always provide fallback — Text inside elements shows if unsupported
- Use form method=“dialog” — For dialog forms to close properly
- Style with CSS — Native elements are customizable
- Add keyboard support — Elements have it built-in
- Use semantic names — Summary should describe content
Common Mistakes
- Not using method=“dialog” — Form won’t close dialog
- Missing summary in details — Summary is required
- Using progress for unknown duration — Use indeterminate progress
- Using meter for exact values — Use number input instead
- Not styling dialogs — Native dialogs look plain without CSS