`<details>` - Expandable details
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">
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
</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:
- Ensure meaningful text within the
<summary>
tag - Add appropriate focus styles for keyboard users
- 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:
- Avoid embedding too many media resources in collapsible content
- Consider lazy-loading images in collapsible content
- 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:
- Do not use
<details>
as a child of<button>
or<a>
- Be mindful of structural integrity when using within
<table>
- 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:
- Increase tap area
- Add touch feedback
- 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>-对话框窗口