折叠面板使用原生 HTML <details> 和 <summary> 元素,利用 name 属性创建独占折叠面板,其中一次只能打开一个项目。这种方法的核心功能不需要 JavaScript,并且默认完全可访问。
示例
点击下方的折叠面板以展开/折叠折叠面板内容。每个 <details> 元素共享相同的 name 属性值,从而创建一个互斥的折叠面板,打开一个项目会自动关闭其他项目。
要呈现默认展开的折叠面板,请将open属性添加到<details>元素。
折叠面板项 #1
open 属性存在。原生 <details> 元素处理所有显示/隐藏逻辑,无需任何 JavaScript。你可以在其中放置任何 HTML 内容 .accordion-body.折叠面板项 #2
name 将此与其他折叠面板项目归为一组。当你打开此项目时,同一组中任何其他打开的项目将自动关闭。折叠面板项 #3
name 你身上的属性 <details> 元素。<div class="accordion">
<details class="accordion-item" name="accordionExample" open>
<summary class="accordion-header">
Accordion Item #1
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
<strong>This is the first item’s accordion body.</strong> It is shown by default because the <code>open</code> attribute is present. The native <code><details></code> element handles all the show/hide logic without any JavaScript. You can put any HTML content within the <code>.accordion-body</code>.
</div>
</details>
<details class="accordion-item" name="accordionExample">
<summary class="accordion-header">
Accordion Item #2
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
<strong>This is the second item’s accordion body.</strong> The <code>name</code> attribute groups this with other accordion items. When you open this item, any other open item in the same group will close automatically.
</div>
</details>
<details class="accordion-item" name="accordionExample">
<summary class="accordion-header">
Accordion Item #3
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
<strong>This is the third item’s accordion body.</strong> This exclusive accordion behavior is built into the browser—no Bootstrap JavaScript required. Just use matching <code>name</code> attributes on your <code><details></code> elements.
</div>
</details>
</div>面板高度动画需要 interpolate-size。不支持它的浏览器会一次性打开和关闭面板。请参阅 过渡 来更改时间或移除它。
此组件的动画效果取决于 prefers-reduced-motion 媒体查询。请参阅我们无障碍文档中的 减少动画部分。
变体
使用上下文 .theme-{color} 类为展开的折叠面板项目应用语义主题颜色。
折叠面板项 #1
open 属性存在。本地的 <details> 元素处理所有显示/隐藏逻辑,无需任何 JavaScript。你可以在其中放置任何 HTML 内容 .accordion-body.折叠面板项 #2
name 将此归类到其他折叠面板项中。当你打开此项时,同一组中的任何其他打开项将自动关闭。折叠面板项 #3
name 你身上的属性 <details> 元素。<div class="accordion theme-primary">
<!-- Accordion items here -->
</div>小
将.accordion-sm添加到.accordion以获得更紧凑的折叠面板,具有更紧的内边距、更小的边框半径和更小的字体大小。
折叠面板项 #1
.accordion-sm 该类收紧了内边距、边框圆角和字体大小,以呈现更紧凑的效果。折叠面板项 #2
折叠面板项目 #3
.accordion-sm 与其他变体如 .accordion-flush 根据需要。<div class="accordion accordion-sm">
<!-- Accordion items here -->
</div>冲洗
添加 .accordion-flush 去除一些边框和圆角,使折叠面板组件与其父容器边缘对齐。
折叠面板项 #1
.accordion-flush 类。这是第一个项目的折叠面板内容。折叠面板项 #2
.accordion-flush 类。这是第二个项目的折叠面板内容区域。让我们想象这里填充了一些实际内容。折叠面板项 #3
.accordion-flush 类。这是第三项的折叠面板内容。在内容方面没有更令人兴奋的事情发生,只是填充空间,以使其看起来,至少乍一看,更像在实际应用中会呈现的样子。<div class="accordion accordion-flush">
<!-- Accordion items here -->
</div>间隙
添加 .accordion-gap 来在折叠面板项目之间留出间距。每个项目都是一个独立的圆角卡片。
间隙存在于折叠面板上,而不是面板上。面板仍然只动画它的 block-size,因此打开和关闭的过渡保持平滑。
折叠面板项目 #1
.accordion-gap 类空间将项目分开。每个项目在面板打开和关闭时保持完整的边框圆角。折叠面板项 #2
折叠面板项目 #3
--accordion-gap 更改项目之间的间距。<div class="accordion accordion-gap">
<!-- Accordion items here -->
</div>--accordion-gap: var(--spacer-2);
始终打开
省略 name 每个属性 <details> 允许多个折叠面板项同时打开的元素。
折叠面板项目 #1
name 属性,每个折叠面板项目独立运行。你可以同时打开多个项目。折叠面板项 #2
name 将它们联系在一起的属性。折叠面板项目 #3
<div class="accordion">
<details class="accordion-item" open>
<!-- No name attribute, so items open independently -->
</details>
<!-- More accordion items here -->
</div>展开 & 折叠全部
要启用一次性展开和折叠所有折叠面板项目,请删除 name 来自每个的属性 <details> 使用 JavaScript 的元素。这允许多个折叠面板项目同时打开。恢复 name 如果你想重新获得独占行为,当你再次折叠项目时请使用该属性。
折叠面板项目 #1
name.折叠面板项 #2
name 分组。折叠面板项 #3
name,你只需要设置 open 在每个项目上。<button type="button" class="btn-subtle btn-sm theme-secondary mb-3" id="btnAccordionToggleAll" aria-expanded="false">Expand all</button>
<div class="accordion accordion-sm" id="accordionExpandCollapse">
<details class="accordion-item" name="accordionExpandCollapse" open>
<summary class="accordion-header">
Accordion Item #1
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
<strong>This is the first item’s accordion body.</strong> Use Expand all to open every item, even when they share a <code>name</code>.
</div>
</details>
<details class="accordion-item" name="accordionExpandCollapse">
<summary class="accordion-header">
Accordion Item #2
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
<strong>This is the second item’s accordion body.</strong> Collapse all closes every item and restores exclusive <code>name</code> grouping.
</div>
</details>
<details class="accordion-item" name="accordionExpandCollapse">
<summary class="accordion-header">
Accordion Item #3
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
<strong>This is the third item’s accordion body.</strong> If your accordion has no <code>name</code>, you only need to set <code>open</code> on each item.
</div>
</details>
</div>我们为此演示使用以下 JavaScript:
const accordion = document.getElementById('accordionExpandCollapse')
const toggleBtn = document.getElementById('btnAccordionToggleAll')
if (accordion && toggleBtn) {
const items = accordion.querySelectorAll('.accordion-item')
const groupName = 'accordionExpandCollapse'
toggleBtn.addEventListener('click', () => {
const expand = toggleBtn.getAttribute('aria-expanded') !== 'true'
for (const item of items) {
if (expand) {
item.removeAttribute('name')
item.open = true
} else {
item.open = false
item.setAttribute('name', groupName)
}
}
toggleBtn.setAttribute('aria-expanded', String(expand))
toggleBtn.textContent = expand ? 'Collapse all' : 'Expand all'
})
}
嵌套
折叠面板可以通过放置一个完整的折叠面板在另一个折叠面板内来嵌套 .accordion 在……之内 .accordion-body. 使用独特 name 为每个级别设置属性值,以便父折叠面板和子折叠面板可以独立运行。
折叠面板项 #1
嵌套项 #1
嵌套项 #2
嵌套项 #3
折叠面板项 #2
折叠面板项 #3
<div class="accordion">
<details class="accordion-item" name="accordionNested" open>
<summary class="accordion-header">
Accordion Item #1
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
<strong>This is the first item’s accordion body.</strong> It contains a nested accordion below.
<div class="accordion mt-3">
<details class="accordion-item" name="accordionNestedInner" open>
<summary class="accordion-header">
Nested Item #1
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
This is the body of the first nested accordion item.
</div>
</details>
<details class="accordion-item" name="accordionNestedInner">
<summary class="accordion-header">
Nested Item #2
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
This is the body of the second nested accordion item.
</div>
</details>
<details class="accordion-item" name="accordionNestedInner">
<summary class="accordion-header">
Nested Item #3
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
This is the body of the third nested accordion item.
</div>
</details>
</div>
</div>
</details>
<details class="accordion-item" name="accordionNested">
<summary class="accordion-header">
Accordion Item #2
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
<strong>This is the second item’s accordion body.</strong> It does not contain a nested accordion.
</div>
</details>
<details class="accordion-item" name="accordionNested">
<summary class="accordion-header">
Accordion Item #3
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m2 5 6 6 6-6"/></svg>
</summary>
<div class="accordion-body">
<strong>This is the third item’s accordion body.</strong> It does not contain a nested accordion.
</div>
</details>
</div>无障碍访问
原生 <details> 和 <summary> 元素提供内置的可访问性:
- 屏幕阅读器会自动宣布展开/折叠状态
- 键盘导航开箱即用(Enter/空格切换)
<summary>元素默认可聚焦- 不需要 ARIA 属性,因为语义已内置在元素中
CSS
变量
折叠面板在.accordion上使用本地 CSS 变量以实现实时自定义。CSS 变量的值由每个组件特有的 Sass map生成,并应用于前述类。
// stylelint-disable-next-line scss/dollar-variable-default
$accordion-tokens: defaults(
(
--accordion-padding-x: 1.25rem,
--accordion-padding-y: 1rem,
--accordion-color: var(--fg-body),
--accordion-bg: var(--bg-body),
--accordion-transition-property: "color, background-color, border-radius",
--accordion-transition-duration: .15s,
--accordion-transition-timing: ease-in-out,
--accordion-panel-transition-property: "content-visibility, block-size",
--accordion-panel-transition-duration: .2s,
--accordion-panel-transition-timing: ease,
--accordion-border-color: var(--border-color),
--accordion-border-width: var(--border-width),
--accordion-border-radius: var(--accordion-radius, var(--radius-7)),
--accordion-gap: 0,
--accordion-btn-color: var(--fg-2),
--accordion-btn-bg: var(--bg-body),
--accordion-btn-icon-width: 1rem,
--accordion-btn-icon-transform: rotate(-180deg),
--accordion-btn-icon-transition: transform .2s ease-in-out,
--accordion-active-color: var(--fg-body),
--accordion-active-bg: var(--bg-2),
),
$accordion-tokens
);
自定义
自定义图标
折叠面板使用内联 SVG 来显示箭头图标。你可以通过替换 .accordion-header 内的 SVG 来自定义它:
<summary class="accordion-header">
Accordion Title
<svg class="accordion-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
<path d="m2 5 6 6 6-6"/>
</svg>
</summary>
.accordion-icon 类负责折叠面板展开时的位置和旋转动画。
事件
你可以倾听本地人 toggle 事件开启 <details> 元素:
const accordionItem = document.querySelector('.accordion-item')
accordionItem.addEventListener('toggle', event => {
if (event.target.open) {
console.log('Accordion opened')
} else {
console.log('Accordion closed')
}
})
编程控制
使用 open 属性以编程方式切换折叠面板项:
const accordionItem = document.querySelector('.accordion-item')
// Open the accordion
accordionItem.open = true
// Close the accordion
accordionItem.open = false
// Toggle the accordion
accordionItem.open = !accordionItem.open