阿里云主机折上折
  • 微信号
Current Site:Index > `<details>` - Expandable details

`<details>` - Expandable details

Author:Chuan Chen 阅读数:53719人阅读 分类: HTML

The <details> tag is a very practical element in HTML5, used to create collapsible content sections. Users can click to expand or hide additional information, making it ideal for displaying extra content or options.

Basic Usage of the <details> Tag

The <details> tag needs to be used in conjunction with the <summary> tag. <summary> defines the visible heading, while <details> contains the collapsible content. By default, the content is hidden.

<details>
  <summary>Click to view details</summary>
  <p>This is the hidden detailed information, which will only be displayed after clicking.</p>
</details>

Default State and the open Attribute

By default, <details> is collapsed. If you want it to be expanded by default, you can add the open attribute.

<details open>
  <summary>Details expanded by default</summary>
  <p>This content is visible by default.</p>
</details>

Nested Use of <details>

<details> can be nested to create multi-level collapsible content.

<details>
  <summary>Level 1 Heading</summary>
  <p>Level 1 content</p>
  <details>
    <summary>Level 2 Heading</summary>
    <p>Level 2 content</p>
  </details>
</details>

Custom Styling

Although <details> has default styling, its appearance can be fully customized with CSS.

<style>
  details {
    border: 1px solid #ddd;
    border-radius: 4px;
    padding: 0.5em;
    margin-bottom: 1em;
  }
  summary {
    font-weight: bold;
    cursor: pointer;
    outline: none;
  }
  details[open] summary {
    color: #0066cc;
  }
</style>

<details>
  <summary>Custom-styled collapsible content</summary>
  <p>After clicking the heading, the content will expand with custom styling.</p>
</details>

JavaScript Interaction

You can listen for the toggle event with JavaScript to perform specific actions when expanding or collapsing.

<details id="interactive-details">
  <summary>Interactive collapsible content</summary>
  <p>An event will be triggered when expanded or collapsed.</p>
</details>

<script>
  document.getElementById('interactive-details').addEventListener('toggle', function(event) {
    if (this.open) {
      console.log('Content expanded');
    } else {
      console.log('Content collapsed');
    }
  });
</script>

Browser Compatibility

Modern browsers generally support the <details> tag, but it is not supported in IE and older versions of Edge. You can use the following polyfill to address compatibility issues:

<script src="https://cdn.jsdelivr.net/npm/details-polyfill@1.2.0/dist/details-polyfill.min.js"></script>

Practical Use Cases

Frequently Asked Questions (FAQ)

<details>
  <summary>How to reset password?</summary>
  <p>Go to the account settings page, click the "Forgot Password" link, and follow the instructions to reset your password.</p>
</details>
<details>
  <summary>What payment methods are supported?</summary>
  <p>We support various payment methods, including credit cards, PayPal, and bank transfers.</p>
</details>

Code Example Display

<details>
  <summary>View HTML example code</summary>
  <pre><code class="language-html">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;Example Page&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1&gt;Hello World&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
  </code></pre>
</details>

Optional Fields in Forms

<form>
  <label>Basic Information</label>
  <input type="text" placeholder="Name">
  
  <details>
    <summary>Advanced Options (Optional)</summary>
    <label>Occupation</label>
    <input type="text">
    <label>Hobbies</label>
    <input type="text">
  </details>
  
  <button type="submit">Submit</button>
</form>

Accessibility Considerations

To ensure all users can use the <details> component, you should:

  1. Ensure meaningful text within the <summary> tag
  2. Add appropriate focus styles for keyboard users
  3. Consider adding ARIA attributes to enhance accessibility
<details aria-labelledby="details-heading">
  <summary id="details-heading" tabindex="0">Accessible collapsible content</summary>
  <p>This content takes accessibility needs into account.</p>
</details>

Performance Considerations

Although the <details> tag itself is lightweight, be mindful when including large amounts of content:

  1. Avoid embedding too many media resources in collapsible content
  2. Consider lazy-loading images in collapsible content
  3. For dynamic content, load it only when expanded for the first time
<details>
  <summary>Content with many images</summary>
  <div class="lazy-content">
    <!-- This content will be loaded via JavaScript when expanded -->
  </div>
</details>

<script>
document.querySelector('details').addEventListener('toggle', function() {
  if (this.open && !this.querySelector('.lazy-content').innerHTML) {
    // Dynamically load content
    this.querySelector('.lazy-content').innerHTML = `
      <img src="image1.jpg" alt="Image 1">
      <img src="image2.jpg" alt="Image 2">
    `;
  }
});
</script>

Interaction with Other HTML Elements

<details> can be used with most HTML elements, but note:

  1. Do not use <details> as a child of <button> or <a>
  2. Be mindful of structural integrity when using within <table>
  3. Ensure no accidental submissions when used with form elements
<!-- Correct usage -->
<details>
  <summary>Form Options</summary>
  <form>
    <input type="checkbox" id="option1">
    <label for="option1">Option 1</label>
  </form>
</details>

<!-- Not recommended -->
<button>
  <details>
    <summary>Don't do this</summary>
    <p>Buttons should not contain details elements</p>
  </details>
</button>

Implementing Animation Effects

Although <details> itself does not support animations, smooth expand/collapse effects can be achieved with CSS and JavaScript.

<style>
  details {
    overflow: hidden;
    transition: height 0.3s ease;
  }
  details:not([open]) {
    height: 2em !important;
  }
</style>

<script>
document.querySelectorAll('details').forEach(details => {
  // Save initial height
  const summary = details.querySelector('summary');
  const content = details.querySelector('summary + *');
  
  details.style.height = `${summary.offsetHeight}px`;
  
  details.addEventListener('toggle', () => {
    if (details.open) {
      details.style.height = `${summary.offsetHeight + content.offsetHeight}px`;
    } else {
      details.style.height = `${summary.offsetHeight}px`;
    }
  });
});
</script>

Usage in Frameworks

In modern frontend frameworks, <details> can be combined with other features.

React Example

function CollapsibleSection({ title, children }) {
  const [isOpen, setIsOpen] = React.useState(false);
  
  return (
    <details open={isOpen} onToggle={() => setIsOpen(!isOpen)}>
      <summary>{title}</summary>
      {children}
    </details>
  );
}

// Usage example
<CollapsibleSection title="Collapsible content in React">
  <p>This is an example of using the details tag in React</p>
</CollapsibleSection>

Vue Example

<template>
  <details :open="isOpen" @toggle="isOpen = $event.target.open">
    <summary>{{ title }}</summary>
    <slot></slot>
  </details>
</template>

<script>
export default {
  props: ['title'],
  data() {
    return {
      isOpen: false
    }
  }
}
</script>

Integration with Web Components

You can create custom collapsible components to enhance <details> functionality.

<script>
class EnhancedDetails extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
      <style>
        :host {
          display: block;
          border: 1px solid #ccc;
          border-radius: 4px;
          padding: 8px;
        }
        summary {
          cursor: pointer;
          font-weight: bold;
        }
        .content {
          padding-top: 8px;
        }
      </style>
      <details>
        <summary><slot name="summary"></slot></summary>
        <div class="content"><slot name="content"></slot></div>
      </details>
    `;
  }
}

customElements.define('enhanced-details', EnhancedDetails);
</script>

<enhanced-details>
  <span slot="summary">Custom collapsible component</span>
  <div slot="content">
    <p>This is an enhanced details component</p>
  </div>
</enhanced-details>

Print Style Handling

When printing pages, you may want to ensure all <details> content is expanded and visible.

@media print {
  details {
    display: block !important;
  }
  details > summary {
    display: none;
  }
  details[open] {
    height: auto !important;
  }
}

Interaction with Shadow DOM

When using <details> in Shadow DOM, be aware of style encapsulation effects.

<div id="host"></div>

<script>
  const host = document.getElementById('host');
  const shadow = host.attachShadow({ mode: 'open' });
  
  shadow.innerHTML = `
    <style>
      details {
        border: 2px dashed blue;
      }
    </style>
    <details>
      <summary>Collapsible content in Shadow DOM</summary>
      <p>The styling here is different from external details</p>
    </details>
  `;
</script>

Mobile Optimization

When using <details> on mobile devices, consider the following optimizations:

  1. Increase tap area
  2. Add touch feedback
  3. Optimize animation performance
/* Mobile-optimized styles */
summary {
  padding: 12px;
  -webkit-tap-highlight-color: transparent;
}

@media (hover: hover) {
  summary:hover {
    background-color: #f5f5f5;
  }
}

Integration with CSS Frameworks

Most CSS frameworks like Bootstrap and Tailwind don't provide direct styling for <details>, but integration is easy.

Tailwind CSS Example

<details class="border rounded-lg overflow-hidden mb-4">
  <summary class="bg-gray-100 px-4 py-3 cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-500">
    Tailwind-styled collapsible content
  </summary>
  <div class="p-4 bg-white">
    <p>Details component integrated with Tailwind CSS</p>
  </div>
</details>

Bootstrap Example

<details class="card">
  <summary class="card-header bg-light" style="cursor: pointer;">
    Bootstrap-styled collapsible content
  </summary>
  <div class="card-body">
    <p class="card-text">Details component integrated with Bootstrap</p>
  </div>
</details>

Dynamic Content Loading

For collapsible panels that need to fetch content from the server, implement dynamic loading.

<details id="dynamic-details">
  <summary>Load dynamic content</summary>
  <div class="content-placeholder">Click to load content...</div>
</details>

<script>
document.getElementById('dynamic-details').addEventListener('toggle', async function() {
  if (this.open && !this.dataset.loaded) {
    const placeholder = this.querySelector('.content-placeholder');
    placeholder.textContent = 'Loading...';
    
    try {
      const response = await fetch('/api/content');
      const data = await response.json();
      placeholder.innerHTML = data.content;
      this.dataset.loaded = true;
    } catch (error) {
      placeholder.textContent = 'Failed to load, please try again';
    }
  }
});
</script>

State Persistence

Use localStorage to save the user's expand/collapse state.

<details id="persistent-details">
  <summary>Collapsible content with saved state</summary>
  <p>The expanded state will be remembered after page refresh.</p>
</details>

<script>
// Restore state
const details = document.getElementById('persistent-details');
details.open = localStorage.getItem('detailsOpen') === 'true';

// Save state
details.addEventListener('toggle', function() {
  localStorage.setItem('detailsOpen', this.open);
});
</script>

Multi-select and Single-select Modes

Implement multi-select or single-select (accordion) effects using JavaScript.

Multi-select Mode

<div class="details-group">
  <details>
    <summary>Item 1</summary>
    <p>Content 1</p>
  </details>
  <details>
    <summary>Item 2</summary>
    <p>Content 2</p>
  </details>
</div>

Single-select Mode (Accordion Effect)

<div class="accordion">
  <details>
    <summary>Accordion Item 1</summary>
    <p>Content 1</p>
  </details>
  <details>
    <summary>Accordion Item 2</summary>
    <p>Content 2</p>
  </details>
</div>

<script>
document.querySelectorAll('.accordion details').forEach(detail => {
  detail.addEventListener('toggle', function() {
    if (this.open) {
      document.querySelectorAll('.accordion details').forEach(other => {
        if (other !== this) other.open = false;
      });
    }
  });
});
</script>

Integration with SVG Icons

Add SVG icons to <summary> to indicate the expand state.

<style>
  details summary {
    list-style: none;
  }
  details summary::-webkit-details-marker {
    display: none;
  }
  .icon {
    transition: transform 0.2s;
  }
  details[open] .icon {
    transform: rotate(90deg);
  }
</style>

<details>
  <summary>
    <svg class="icon" width="16" height="16" viewBox="0 0 24 24">
      <path d="M8.59 16.58L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42z"/>
    </svg>
    Collapsible content with icon
  </summary>
  <p>The icon will rotate when expanded</p>
</details>

Keyboard Navigation Support

Ensure the <details> component can be fully operated via keyboard.

<details>
  <summary tabindex="0">Keyboard-navigable</summary>
  <p>Can be focused with Tab and toggled with Enter or Space</p>
</details>

<script>
document.querySelectorAll('details summary').forEach(summary => {
  summary.addEventListener('keydown', function(e) {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      this.parentElement.open = !this.parentElement.open;
    }
  });
});
</script>

Integration with Form Validation

Include form validation logic within collapsible content.

<form id="myForm">
  <details>
    <summary>Advanced Options</summary>
    <div>
      <label>
        Captcha:
        <input type="text" name="captcha" required>
      </label>
    </div>
  </details>
  <button type="submit">Submit</button>
</form>

<script>
document.getElementById('myForm').addEventListener('submit', function(e) {
  const details = this.querySelector('details');
  if (details.open && !this.captcha.value) {
    e.preventDefault();
    alert('Please fill in the captcha');
    details.querySelector('input').focus();
  }
});
</script>

Performance Monitoring

Monitor <details> usage to understand user interactions.

<details data-track="faq-section">
  <summary>Most Frequently Asked Question</summary>
  <p>Here is the answer to the question...</p>
</details>

<script>
document.querySelectorAll('details[data-track]').forEach(details => {
  details.addEventListener('toggle', function() {
    if (this.open) {
      const eventName = this.getAttribute('data-track');
      // Send analytics event
      console.log(`Tracked: ${eventName} opened`);
    }
  });
});
</script>

Integration with Web Animations API

Use the Web Animations API to add more complex animations to <details>.

<details id="animated-details">
  <summary>Collapsible content with complex animation</summary>
  <div class="content">
    <p>This content will expand and collapse with animation</p>
  </div>
</details>

<script>
const details = document.getElementById('animated-details');
const content = details.querySelector('.content');

details.addEventListener('toggle', function() {
  if (this.open) {
    // Expand animation
    content.animate([
      { height: '0', opacity: 0 },
      { height: `${content.scrollHeight}px`, opacity: 1 }
    ], {
      duration: 300,
      easing: 'ease-out'
    });
  } else {
    // Collapse animation
    content.animate([
      { height: `${content.scrollHeight}px`, opacity: 1 },
      { height: '0', opacity: 0 }
    ], {
      duration: 200,
      easing: 'ease-in'
    });
  }
});
</script>

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:

-细节摘要

下一篇:<dialog>-对话框窗口

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.