前言
手风琴是一种常见的网页 UI 模式,通常是一系列垂直堆叠的标题可以用于展开收合显示不同资讯,也有额外的称呼像是:
- Collapsible
- Details
- Expandable
而在 HTML 当中有项新颖的语法 <details>
和 <summary>
可以帮助我们快速实现类似的功能,并且配合上新的 CSS interpolate-size
和 transition-behavior
制作滑顺的展开闭合动画。
基础手风琴
HTML 添加了 <details>
让我们可以用原生的方式表达可被开合的区块,其中 <summary>
代表区块的标题,范例如下:
<details> <summary>Section Summary Title Here</summary> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ad consectetur nisi repellendus atque. Praesentium mollitia sapiente libero aspernatur. Hic ipsa id eveniet sapiente totam soluta exercitationem iusto, quaerat delectus ratione.</details>
Section Summary Title Here
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ad consectetur nisi repellendus atque. Praesentium mollitia sapiente
libero aspernatur. Hic ipsa id eveniet sapiente totam soluta exercitationem iusto, quaerat delectus ratione.
群组手风琴
要绑定多个手风琴开合状态的话可以使用相同的 name
属性,这样就能强制只能打开单个相同 name
属性的手风琴:
<details name="exclusive"> <summary>Section 1</summary> <p>Content for section 1.</p></details><details name="exclusive"> <summary>Section 2</summary> <p>Content for section 2.</p></details>
Section 1
Content for section 1.
Section 2
Content for section 2.
预设开启手风琴
要预设特定手风琴项目开启的话可以使用 open
属性:
<details open> <summary>Section 1</summary> <p>Content for section 1.</p></details>
Section 1
Content for section 1.
添加动画
要选择 details 的内容可以使用 ::details-content 伪元素,在开启的状态设置不同的高度与 transition
就可以根据开合状态进行动画。
details::details-content { background-color: red; height: 0; transition: height 1s;}
details[open]::details-content { height: auto;}
使高度能被动画: interpolate-size: allow-keyword
会发现就算添加 transition
指示元素伸展收合时 height
也不会有任何的动画,在早期这个问题算是无解了,只能用 JS 去计算高度并更改属性来达成动画效果。幸好如今有全新的实验性 CSS 语法:interpolate-size: allow-keywords
(尺寸插值变化允许关键字) 协助我们替 auto
、fit-content
、max-content
这类属性计算 animation
与 transition
。它是一种可以被子元素继承的样式设置,所以就算设定在文件根部或个别使用的元素上都可行:
:root { interpolate-size: allow-keywords;}
使显示可被动画: content-visibility
会发现在收阖时不会有任何动画而是直接消失,这是因为手风琴关闭时内容显示会被设置为无,针对这点我们也会需要设置相关的动画,并且它是种 discrete 动画!意味着它不会存在中间状态或数值,会需要 transition-behavior: allow-discrete
才能让其他动画完成后才进行切换:
transition: height 1s, content-visibility 1s;transition-behavior: allow-discrete;
总结
如果依照前面的步骤操作下来,你会得到一个最小可运作的原生手风琴,并且有不错的开阖动画!此外可以参考看看 Kevin Powell 更精致的实践以及他的介绍影片:Animate details & summary with a few lines of CSS - Kevin Powell
See the Pen details & summary by Riceball (
@riecball) on CodePen.
延伸阅读
- Accordion - the component gallery
- Native HTML: Accordion Revisited - Andrew Bone
- This new CSS property just solved animating to height auto - Kevin Powell
- 这啥?CSS calc-size 和 interpolate-size,真学不动了 - 鑫空间-鑫生活
- interpolate-size - MDN