Collapsible HTML Tags, Attributes and Elements Reference

html html-tags html-attributes collapsible-html semantic-html

Collapsible HTML sections let you show and hide content without writing any JavaScript — the <details> and <summary> elements handle that natively in every modern browser. This reference covers collapsible HTML fully, then walks through the tags, attributes, and semantic elements you’ll use most when building web pages. Whether you’re adding a FAQ accordion, marking up navigation, or putting together a contact form, you’ll find the syntax and context you need here.

Collapsible HTML: The <details> and <summary> Elements

The <details> element creates a disclosure widget: a block of content that starts collapsed and expands when a user clicks it. The <summary> element provides the clickable heading. Both are supported across all major browsers without any polyfill or JavaScript dependency.

Here’s the minimal working structure:

<details>
  <summary>Show installation instructions</summary>
  <p>Run <code>npm install</code> from your project root directory.</p>
</details>

The <summary> tag must be the first child of <details>. If you omit it, browsers display a default label — usually “Details”. Everything after <summary> is the collapsible content: it can contain paragraphs, lists, code blocks, images, tables, or even nested <details> elements.

The open Attribute

By default the content inside <details> is hidden. Add the open attribute to start it expanded:

<details open>
  <summary>Prerequisites</summary>
  <ul>
    <li>Node.js 18 or higher</li>
    <li>npm or yarn installed globally</li>
    <li>A code editor</li>
  </ul>
</details>

open is a boolean attribute — its presence means open, its absence means closed. You can read or set it with JavaScript when you need programmatic control:

const disclosureEl = document.querySelector('details#prerequisites');

// Expand it
disclosureEl.open = true;

// Collapse it
disclosureEl.open = false;

// Toggle
disclosureEl.open = !disclosureEl.open;

Listening to State Changes with toggle

The <details> element fires a toggle event whenever its state changes. Use this event to track interactions, trigger animations, or keep multiple collapsible sections in sync:

const detailsEl = document.querySelector('details.faq-item');

detailsEl.addEventListener('toggle', () => {
  const state = detailsEl.open ? 'opened' : 'closed';
  analytics.track('faq_disclosure', { state });
});

Styling Collapsible HTML

The browser renders a disclosure triangle (▶) by default. You can hide it and apply your own styles using the ::marker pseudo-element and an [open] attribute selector:

details summary {
  cursor: pointer;
  font-weight: 600;
  padding: 0.5rem 0.75rem;
  background: #f5f5f5;
  border-radius: 4px;
  list-style: none;
}

/* Needed for Chrome and Safari */
details summary::-webkit-details-marker {
  display: none;
}

details[open] summary {
  background: #e8f4fd;
  border-bottom: 1px solid #c8e0f4;
}

details > *:not(summary) {
  padding: 0.75rem;
  border: 1px solid #e0e0e0;
  border-top: none;
  border-radius: 0 0 4px 4px;
}

For smooth expand/collapse animation, you can pair this with a CSS transition on max-height, though the native <details> doesn’t support height: auto transitions directly — a small JavaScript wrapper handles that case.

Collapsible HTML with <details> and <summary> fits well for FAQ sections, optional code examples, long inline notes, settings panels, and any place you want optional content to stay out of the way by default. For the MDN full reference on the <details> element, see the MDN <details> documentation.


Essential HTML Tags: A Practical Reference

Every HTML page is built from a repeating core of high-frequency tags. The tables below cover the elements you’ll write on nearly every project, organized by role.

Document Structure

TagPurposeNotes
<!DOCTYPE html>Declares HTML5 modeAlways the first line of any HTML document
<html lang="en">Root elementAlways set the lang attribute
<head>Metadata containerNot rendered in the browser viewport
<body>Page contentEvery visible element goes inside here
<title>Browser tab title50–60 characters optimal for search appearance
<meta>Metadata — charset, viewport, descriptionSelf-closing; no end tag needed
<link>External resource — CSS, fonts, canonicalSelf-closing
<script>JavaScriptAdd defer or async to avoid blocking rendering
<style>Inline CSSPrefer external stylesheets for maintainability
<base>Base URL for relative linksAt most one per document

Text Content

TagPurposeNotes
<p>ParagraphBlock element; use CSS margins for spacing
<h1><h6>HeadingsOne <h1> per page; never skip levels
<span>Inline containerNo semantic meaning; useful for styling hooks
<div>Block containerNo semantic meaning; used for layout grouping
<br>Line breakFor intentional breaks in prose, not spacing
<hr>Thematic breakVisual separator between distinct topics
<pre>Preformatted textPreserves whitespace and line breaks as typed
<code>Inline codePair with <pre> for multi-line code blocks
<strong>Bold + semantic importanceScreen readers may signal importance
<em>Italic + semantic emphasisSignals stress emphasis affecting meaning
<blockquote>Extended quotationAdd cite attribute with the source URL
<abbr>AbbreviationUse title for the expanded form
<kbd>Keyboard inputRenders key-like styling by default
<del> / <ins>Deleted / inserted textUseful in changelogs and edit tracking
<sub> / <sup>Subscript / superscriptFor chemical formulas and footnote references

Lists

TagPurposeNotes
<ul>Unordered listBullet points; use list-style-type to change style
<ol>Ordered listNumbers by default; type changes to letters or roman numerals
<li>List itemUsed inside <ul> or <ol> only
<dl>Description listFor term–definition pairs and metadata tables
<dt>Description termAlways a child of <dl>
<dd>Description detailsAlways a child of <dl>, follows <dt>
TagPurposeNotes
<a>Hyperlinkhref, target="_blank", rel
<img>ImageSelf-closing; alt required; use loading="lazy" below the fold
<video>Video playerWrap <source> children for multiple formats
<audio>Audio playerSame <source> pattern as <video>
<picture>Responsive imagesWraps <source> elements + fallback <img>
<figure>Media with optional captionPair with <figcaption>
<figcaption>Caption for a <figure>Can precede or follow the media element
<canvas>2D drawing surfaceRequires JavaScript to draw
<svg>Inline vector graphicScales without quality loss at any size
<iframe>Embedded pageUse sandbox attribute for untrusted content

For the full elements reference with browser compatibility data, the MDN HTML elements reference covers every tag in the specification.


HTML Attributes Reference

Attributes modify element behavior and provide machine-readable context. Global attributes apply to every HTML element. Per-element attributes only work on specific tags.

Global Attributes

AttributeValueDescription
idUnique stringCSS target, JavaScript handle, anchor fragment
classSpace-separated listCSS and JavaScript targeting
styleCSS declarationsInline styles; prefer external CSS for maintainability
langBCP 47 language tagen, fr, zh-Hant; overrides the document language
dirltr or rtlText flow direction
titleStringTooltip text shown on hover
hiddenBooleanHides element from rendering; keeps it in the DOM
tabindexIntegerKeyboard focus order; -1 removes from tab sequence
data-*Custom stringCustom data attached directly to elements
aria-*ARIA valueAccessibility state and properties
roleARIA roleSemantic role for screen readers
contenteditabletrue or falseMakes element editable in place
draggabletrue or falseEnables HTML5 drag-and-drop on this element
autofocusBooleanFocus this element on page load (one per page)
translateyes or noWhether translation services should translate the text

The <a> element’s rel attribute controls how browsers and search engines treat the link. Two values matter most in practice:

<!-- Opens in a new tab and prevents tabnapping -->
<a
  href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element"
  target="_blank"
  rel="noopener noreferrer">
  MDN HTML elements reference
</a>

rel="noopener" prevents the opened page from accessing window.opener, blocking a class of phishing attack. rel="noreferrer" also suppresses the Referer header. Always add both when using target="_blank".

For images, alt is required on every <img> element. An empty alt="" tells screen readers to skip the image — use it for decorative images only. Omitting alt entirely causes screen readers to announce the filename:

<!-- Informative image: describe what it shows -->
<img
  src="/screenshots/collapsible-section-open.png"
  alt="HTML details element expanded, showing a nested unordered list"
  width="720"
  height="400"
  loading="lazy">

<!-- Decorative image: empty alt skips it in screen readers -->
<img src="/ui/decorative-wave.svg" alt="" role="presentation">

The loading="lazy" attribute defers loading until the image nears the viewport — a free performance improvement for images below the fold. This complements techniques in our HTML minification and compression guide, which covers reducing HTML file size before delivery.


Semantic HTML: Structuring Pages With Meaning

Semantic elements describe the role of their content, not just how it looks. Screen readers, search crawlers, and browser reading modes all use these signals to understand page structure — without parsing CSS class names.

Here are the landmark and content-sectioning elements and when to reach for each:

ElementUse when…Don’t use when…
<header>Introducing a page or section — site logo, main nav, heroWrapping all page content
<nav>A set of navigation linksEvery group of links; use it for primary and secondary nav only
<main>The primary, unique content areaThere’s more than one per page
<article>Self-contained content that makes sense standalone — post, news item, commentContent that requires surrounding context
<section>Thematically grouped content that needs a headingContent with no clear thematic grouping (use <div>)
<aside>Content tangentially related to main content — sidebar, callout, related linksPrimary content of the page
<footer>Closing content for the page or its ancestor sectionJust any bottom-aligned div
<time>A date, time, or durationOther text that happens to mention time loosely
<address>Contact information for the nearest <article> or page authorPhysical addresses unrelated to the document author
<mark>Highlighted text, typically search result matchesGeneric emphasis (use <em> or <strong>)
<dialog>A dialog box or modalContent that should always be visible
<details>Collapsible disclosure contentContent that should always be visible

A well-structured article page using these together:

<body>
  <header>
    <nav aria-label="Site navigation">
      <a href="/">DevNook</a>
      <a href="/guides/">Guides</a>
      <a href="/cheatsheets/">Cheatsheets</a>
    </nav>
  </header>

  <main>
    <article>
      <header>
        <h1>Getting Started with Collapsible HTML</h1>
        <time datetime="2026-06-10">June 10, 2026</time>
      </header>

      <section>
        <h2>The &lt;details&gt; Element</h2>
        <p>Use <code>&lt;details&gt;</code> to create expand-on-click sections without JavaScript.</p>

        <details>
          <summary>See a complete working example</summary>
          <pre><code class="language-html">&lt;details&gt;
  &lt;summary&gt;Advanced options&lt;/summary&gt;
  &lt;p&gt;Configure timeout, retries, and proxy settings here.&lt;/p&gt;
&lt;/details&gt;</code></pre>
        </details>
      </section>

      <aside>
        <p>Working on layout? The
          <a href="/blog/css-flexbox-vs-grid">CSS Flexbox vs. Grid comparison</a>
          explains which model to reach for.
        </p>
      </aside>
    </article>
  </main>

  <footer>
    <p>&copy; 2026 DevNook</p>
  </footer>
</body>

The rule of thumb: use the semantic element when the role matters to accessibility or SEO; use <div> or <span> when you only need a layout or styling hook.


HTML Forms: Input Types and Validation Attributes

Forms collect user input. The <form> element’s action and method attributes control the submission target and HTTP method. Pairing form elements with correct <label> associations keeps forms accessible and usable.

<form action="/contact" method="post">
  <label for="visitor-name">Name</label>
  <input
    type="text"
    id="visitor-name"
    name="visitor_name"
    required
    minlength="2"
    maxlength="80"
    autocomplete="name">

  <label for="visitor-email">Email address</label>
  <input
    type="email"
    id="visitor-email"
    name="visitor_email"
    required
    autocomplete="email">

  <label for="visitor-message">Message</label>
  <textarea
    id="visitor-message"
    name="message"
    rows="5"
    minlength="20"
    maxlength="2000">
  </textarea>

  <button type="submit">Send message</button>
</form>

Input Types Reference

HTML5 input types activate browser-native validation and contextual mobile keyboards automatically:

type valuePurposeKey attributes
textGeneral single-line textDefault when type is unspecified
emailEmail addressValidates format; mobile keyboard shows @ key
passwordMasked inputBrowser may offer to save and autofill
numberNumeric inputmin, max, step
telTelephone numberMobile shows dial pad; no format validation
urlURLValidates that it starts with a scheme
dateDate pickerReturns YYYY-MM-DD; native UI varies by OS
timeTime pickerReturns HH:MM; local time, no timezone
datetime-localDate and time pickerLocal time; no timezone information
rangeSlider controlmin, max, step, value
checkboxBoolean toggleUse checked attribute for default-on state
radioSingle selection from a groupSame name value groups radio inputs together
fileFile uploadaccept filters by type; multiple allows several files
hiddenNot rendered to userSubmits a fixed value with the form
submitSubmits the formOr use <button type="submit"> for more control
resetResets all fields to defaultsRarely useful; can frustrate users who click it by mistake
searchSearch fieldBrowser may add a clear button
colorColor pickerReturns a lowercase hex string like #3a7bd5
monthMonth and year pickerReturns YYYY-MM

Form Validation Attributes

Native browser validation runs before submission without requiring JavaScript:

AttributeApplies toWhat it does
requiredinput, select, textareaField must not be empty at submit time
minlengthtext-type inputs, textareaMinimum character count
maxlengthtext-type inputs, textareaMaximum character count (hard limit in some browsers)
minnumber, date, range, timeMinimum allowed value
maxnumber, date, range, timeMaximum allowed value
stepnumber, range, date, timeValid increment for the value
patterntext-type inputsA regex the value must match fully
novalidate<form> elementDisables native validation for the entire form
formnovalidatesubmit buttonDisables validation for that specific button only
autocompleteform, inputon, off, or a named token like email or new-password
placeholdertext-type inputsHint text shown when the field is empty
readonlyinput, textareaDisplayed but not editable; still submitted
disabledinput, select, textarea, buttonNot interactive and not included in form submission

Form validation errors and the HTTP responses they produce are connected — the HTTP status codes guide covers the 400, 422, and 200 response codes you’ll encounter when processing form submissions server-side.


Common HTML Mistakes That Break Silently

These mistakes won’t crash your page — browsers fix them silently — but they surface as accessibility failures, layout bugs, or SEO penalties.

Missing alt on meaningful images. Every <img> carrying visual information needs a descriptive alt. Empty alt="" is correct only for decorative images. Omitting the attribute entirely causes screen readers to read out the filename. Write alt text that describes the image’s purpose, not its appearance: “Chart showing monthly revenue Q1–Q4 2025” beats “revenue chart”.

Using <br> for layout spacing. <br> creates a line break within text content — it’s correct in addresses and poetry. Using <br><br> to add space between elements is a layout concern: handle it with CSS margin or padding.

Missing for/id pairing on labels. Without this association, screen readers can’t tell which label belongs to which field, and clicking the label doesn’t focus the input:

<!-- Wrong: label and input are not associated -->
<label>Email</label>
<input type="email" name="email">

<!-- Right: clicking the label focuses the input -->
<label for="contact-email">Email</label>
<input type="email" id="contact-email" name="email">

Scripts in <head> without defer. A <script src="app.js"> in <head> blocks HTML parsing until the script downloads and executes. Add defer to let HTML continue parsing while the script downloads:

<head>
  <meta charset="UTF-8">
  <title>My App</title>
  <!-- Downloads in parallel; executes after DOM is ready -->
  <script src="app.js" defer></script>
</head>

Using <table> for page layout. Tables are for tabular data — rows and columns with a meaningful relationship. Using them to control visual layout breaks the reading order for screen readers and makes responsive design very difficult. Use CSS Flexbox or Grid instead, as covered in the CSS Flexbox vs. Grid guide.

Skipping heading levels. Going from <h2> to <h4> breaks the document outline used by screen readers to navigate pages. Each level should represent a true hierarchical step in your content structure.


Frequently Asked Questions

What is collapsible HTML and how do I create it?

Collapsible HTML refers to content that can be shown or hidden by user interaction. The native HTML approach uses the <details> element as the container and <summary> as the clickable heading. Add a <details> block to your page, put a <summary> as its first child — that’s the visible toggle — then add your collapsible content after the summary tag. No JavaScript or CSS is required for the basic toggle. Add the open attribute to <details> to start it expanded on page load. The behavior works in all major browsers and degrades gracefully in environments that don’t support it by showing all content by default.

What is the difference between <strong> and <b> in HTML?

<strong> and <b> both render bold text visually, but they carry different semantic weight. <strong> marks text as important — screen readers may change their intonation to signal it, and it affects how the content is interpreted in contexts like text-to-speech. <b> is for stylistic bold that doesn’t imply importance: product names, technical terms, or keywords in search results. The same distinction applies between <em> (stress emphasis that affects meaning, analogous to how you’d say the word aloud) and <i> (offset text like book titles, technical terms, or foreign words).

When should I use <article> versus <section> in HTML?

Use <article> when the content makes sense on its own — a blog post, a news item, a product card, a user comment. You could syndicate it to an RSS feed or embed it on a different page and it would still be coherent. Use <section> for a thematically grouped block within a page that requires surrounding context to make sense. An <article> can contain multiple <section> elements. A <section> should not contain multiple unrelated <article> elements. When neither fits cleanly, a <div> is appropriate — it adds no incorrect semantics.

What does defer do on a <script> tag and when should I use async?

defer downloads the script in parallel with HTML parsing, then executes it after parsing is complete but before the DOMContentLoaded event. Multiple deferred scripts execute in document order. async also downloads in parallel, but executes as soon as the download finishes — potentially interrupting HTML parsing and without preserving order. Use defer for scripts that interact with the DOM or need to run after other scripts. Use async for independent scripts that don’t depend on DOM state, like third-party analytics or ad tags. For scripts placed at the end of <body>, neither attribute is necessary — the DOM is already parsed by the time they run — though defer in <head> is generally the better pattern.

What is the data-* attribute in HTML and when should I use it?

data-* attributes store custom data on HTML elements without inventing non-standard attributes. Replace the * with a lowercase name: data-product-id, data-theme, data-section-index. Values are always strings. JavaScript reads them via element.dataset.productId — the attribute name after data- converted to camelCase. They’re useful for passing server-rendered data to client scripts, marking elements for JavaScript behavior, and storing metadata without adding invisible DOM nodes. They’re not suited for large or frequently changing data — a JavaScript variable, a fetch() call, or a structured data store handles those cases better.


Conclusion

Collapsible HTML through <details> and <summary> removes the need for JavaScript toggle logic across a wide range of disclosure patterns — FAQ sections, optional code previews, settings panels. Paired with the semantic structure, attribute patterns, and HTML5 form controls in this reference, you have the core vocabulary for building accessible, well-structured web pages. To reduce the size of your HTML output before deploying, see the HTML minification and compression guide. For page layout decisions once your markup is solid, the CSS Flexbox vs. Grid comparison explains which model to reach for.