最近details
元素新增了一个name
属性,如下
别看这只是一个普普通通的属性,这可是带来了一个全新的模式,一起了解一下吧
一、快速了解 details 有些同学可能从来没有用过details
这个标签,这里简单介绍一下。
details
通常和summary
配合使用,天然支持展开收起的效果。例如
<details> <summary>System Requirements</summary> <p>Requires a computer running an operating system. The computer must have some memory and ideally some kind of long-term storage. An input device as well as some form of output device is recommended.</p> </details>
效果如下
虽然有些难看,但都是可以通过 CSS
自定义的。 如果想去除这个“黑色三角”,这个“黑色三角”其实是 ::marker
生成的,,而这个 ::marker
是通过list-style
生成,所以要去除可以这样
summary{ list-style: none; } /*或者*/ summary{ display: flex; /*默认是list-style*/ }
还支持嵌套,进一步美化可以实现树形结构目录
有兴趣的可以回顾一下之前这篇文章:
CSS 实现树状结构目录
以后碰到类似的交互就直接用这个标签吧,别用JS
了
二、新增的 name 属性 和大多数表单元素一样,这个name
也是可以直接设置和获取的
details.name; // 获取 details.name = 'xxx'; // 设置
除此之外,还支持了“手风琴”模式。所谓“手风琴”模式,相信大家都有所耳闻,就是多个折叠面板,打开其中一个会关闭其他的,比如下方是ant design
中的手风琴效果
现在如果用details
就可以很轻易的实现这个效果,结构如下
<div class="con"> <details> <summary>欢迎</summary> <p>最近 details元素新增了一个name属性</p> </details> <details> <summary>关注</summary> <p>别看这只是一个普普通通的属性,这可是带来了一个全新的模式,一起了解一下吧</p> </details> <details> <summary>前端</summary> <p>details通常和summary配合使用,天然支持展开收起的效果</p> </details> <details> <summary>侦探</summary> <p>虽然有些难看,但都是可以通过 CSS 自定义的</p> </details> </div>
效果如下
嗯,有点丑...我们美化一下
.con{ width: 300px; border-radius: 8px; border: 1px solid #9747FF; background-color: #fdf0ca ; overflow: hidden; } summary{ display: flex; align-items: center; line-height: 2; padding: 0 10px; cursor: pointer; border-bottom: 1px solid #9747FF; background-color: #FFE8A3; } summary::before{ content: ''; width: 20px; height: 20px; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E %3Cpath d='M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z'%3E%3C/path%3E %3C/svg%3E") center/50% no-repeat; opacity: .6; transform: rotate(-90deg); } details[open] summary::before{ transform: rotate(0deg); } p{ margin: 0; padding: 5px 10px; border-bottom: 1px solid #9747FF; } details:last-child p, details:last-child:not([open]) summary{ border: 0; }
效果如下
不过现在每个折叠面板是互相独立的,都可以打开或者关闭。
现在我们想要把这几个面板关联起来,就像单选框一样,用相同的name
表示
<div class="con"> <details name="a"> <summary>欢迎</summary> <p>最近 details元素新增了一个name属性</p> </details> <details name="a"> <summary>关注</summary> <p>别看这只是一个普普通通的属性,这可是带来了一个全新的模式,一起了解一下吧</p> </details> <details name="a"> <summary>前端</summary> <p>details通常和summary配合使用,天然支持展开收起的效果</p> </details> <details name="a"> <summary>侦探</summary> <p>虽然有些难看,但都是可以通过 CSS 自定义的</p> </details> </div>
这样就是实现了手风琴的效果了
是不是非常简单呢?
三、还是需要 polyfill 一下 虽然好用,但是兼容性还不行,需要用一段 JS
来兜个底。
首先我们需要判断一下,也就是检测details
到底支不支持name
这个特性,这个很简单,我们只需要创建一个details
元素,然后看这个属性是否存在就行了,如下
'name' in document.createElement('details');
效果如下
对于不支持的浏览器,我们就需要通过监听打开关闭状态了,直接监听click
事件
details
元素其实还有一个toggle
事件,也可以用于监听,但是在这里不太合适,因为toggle
是在状态改变后才触发,有点晚了,会造成闪烁的问题
我们需要监听所有的details
元素,然后根据name
属性,把其他相同name
的都关闭,具体实现如下
// details name polyfill if (!('name' in document.createElement('details'))) { const details = [...document.querySelectorAll('details')] details.forEach(el => { el.addEventListener('click', () => { if (!el.open) { details.filter(d => d.getAttribute('name') === el.getAttribute('name') && d!==el && d.open).forEach(m => { m.open = false }) } }) }) }
我们现在来看Firefox
的效果
同样支持多个分组,每个分组设置相同的name
就行
完整代码可以访问以下链接:
四、总结一下 总的来说是一个不痛不痒的新特性,你学到了,下面总结一下
details
通常和summary
配合使用,天然支持展开收起的效果
summary
前面的黑色三角形是::marker
渲染的,可以通过设置list-style: none
去除
新增的name
属性可以直接通过dom.name
的方式设置和获取
多个details
元素添加name
属性后会变成手风琴模式,即打开其中一个会关闭其他
目前兼容性还不行,需要polyfill
一下
可以通过'name' in document.createElement('details')
来检测是否支持该特性
不过这个特性毕竟可替代性太强了,直接 JS
一把梭也能实现,国内估计没几个会用上。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发 ❤❤❤
[1] details with name (juejin.cn): https://code.juejin.cn/pen/7320515540379041843
[2] details with name (codepen.io): https://codepen.io/xboxyan/pen/abMdMOV