Figure & Details

Difficulty: Intermediate

HTML5 introduced several specialized semantic elements for common content patterns. The <figure> and <figcaption> pair provides a standard way to associate captions with images, code blocks, diagrams, and other referenced content. The <details> and <summary> pair creates native disclosure widgets without JavaScript. The <dialog> element provides a built-in modal/dialog box. These elements reduce the need for custom JavaScript solutions and improve accessibility out of the box.

The <figure> element represents self-contained content that is referenced from the main flow of the document but could be moved to an appendix, sidebar, or separate page without affecting the main content's meaning. Figures are typically images, illustrations, diagrams, code snippets, or tables. The <figcaption> element provides the caption and must be either the first or last child of <figure>. Importantly, <figure> is not just for images - any content that deserves a caption can be wrapped in a figure.

The <details> element creates a disclosure widget that the user can open and close without any JavaScript. Its child <summary> element provides the visible label when the widget is closed. Everything else inside <details> is hidden until the user clicks to expand it. The open attribute controls the initial state. This is perfect for FAQs, collapsible sections, and progressive disclosure patterns. The browser handles all the toggle behavior natively, including keyboard accessibility.

The <dialog> element represents a dialog box or interactive component such as a modal window, confirmation dialog, or alert. Unlike building modals with divs and CSS, the native <dialog> element provides built-in focus trapping, keyboard handling (Escape to close), and the ::backdrop pseudo-element for overlay styling. You control it programmatically with the showModal() and close() methods. The showModal() method opens the dialog as a modal (blocking interaction with the rest of the page), while show() opens it as a non-modal dialog.

These elements share a common philosophy: use native HTML capabilities before reaching for JavaScript. Native elements come with built-in accessibility, keyboard support, and consistent behavior across browsers. Custom implementations often miss edge cases - focus trapping, screen reader announcements, keyboard navigation - that native elements handle automatically.

Code examples

Figure with Different Content Types

<!-- Figure with image -->
<figure>
  <img src="/images/chart.png" alt="Sales data for Q1 2026">
  <figcaption>Figure 1: Q1 2026 sales showed a 15% increase over Q4 2025.</figcaption>
</figure>

<!-- Figure with code block -->
<figure>
  <pre><code>const greeting = (name) => {
  return `Hello, ${name}!`;
};</code></pre>
  <figcaption>Example: An arrow function that returns a greeting string.</figcaption>
</figure>

<!-- Figure with blockquote -->
<figure>
  <blockquote>
    "The best way to predict the future is to invent it."
  </blockquote>
  <figcaption>Alan Kay, 1971</figcaption>
</figure>

Figures work with any referenced content: images, code blocks, quotes, diagrams, tables. The figcaption provides context that helps users understand what they are looking at.

Details and Summary Patterns

<!-- Basic FAQ accordion -->
<details>
  <summary>What is semantic HTML?</summary>
  <p>Semantic HTML uses elements that describe the meaning of content, such as &lt;article&gt;, &lt;nav&gt;, and &lt;header&gt;, rather than generic &lt;div&gt; elements.</p>
</details>

<details>
  <summary>Why does it matter?</summary>
  <p>It improves accessibility for screen readers, helps search engines understand your content, and makes code more maintainable.</p>
</details>

<!-- Open by default -->
<details open>
  <summary>Getting Started (expanded by default)</summary>
  <p>Start by replacing your most common div patterns with semantic alternatives.</p>
  <ol>
    <li>Replace div.header with &lt;header&gt;</li>
    <li>Replace div.nav with &lt;nav&gt;</li>
    <li>Replace div.footer with &lt;footer&gt;</li>
  </ol>
</details>

The details/summary pattern creates native collapsible sections. No JavaScript is needed. The open attribute controls the initial state. Users can click the summary or press Enter/Space to toggle.

Native Dialog Element

<!-- Dialog element in HTML -->
<button id="open-btn">Open Dialog</button>

<dialog id="my-dialog">
  <h2>Confirm Action</h2>
  <p>Are you sure you want to delete this item?</p>
  <form method="dialog">
    <button value="cancel">Cancel</button>
    <button value="confirm">Confirm</button>
  </form>
</dialog>

<script>
  const dialog = document.getElementById('my-dialog');
  const openBtn = document.getElementById('open-btn');

  openBtn.addEventListener('click', () => {
    dialog.showModal(); // Opens as modal with backdrop
  });

  dialog.addEventListener('close', () => {
    console.log('Dialog result:', dialog.returnValue);
  });
</script>

The dialog element with showModal() provides focus trapping, Escape key to close, and a ::backdrop pseudo-element. The form method='dialog' automatically closes the dialog and sets returnValue to the clicked button's value.

Styling Details and Dialog

<!-- Custom styled details -->
<style>
  details {
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 8px;
  }
  details[open] {
    background-color: #f8fafc;
  }
  summary {
    cursor: pointer;
    font-weight: 600;
    padding: 4px 0;
  }
  summary::marker {
    color: #3b82f6;
  }
  dialog::backdrop {
    background: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(4px);
  }
  dialog {
    border: none;
    border-radius: 12px;
    padding: 24px;
    max-width: 400px;
    box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
  }
</style>

<details>
  <summary>Styled Collapsible Section</summary>
  <p>This section has custom borders, background, and marker color.</p>
</details>

Both details and dialog are fully stylable with CSS. The [open] attribute selector targets the expanded state. The ::marker pseudo-element styles the disclosure triangle. The ::backdrop pseudo-element styles the modal overlay.

Key points

Concepts covered

figure, figcaption, details, summary, dialog, Interactive Elements