原生Details支持手风琴模式了!

开发 前端
首先我们需要判断一下,也就是检测details到底支不支持name这个特性,这个很简单,我们只需要创建一个details元素,然后看这个属性是否存在就行了。

最近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*/
}

还支持嵌套,进一步美化可以实现树形结构目录

图片图片

以后碰到类似的交互就直接用这个标签吧,别用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 with name (juejin.cn)[1]
  • details with name (codepen.io)[2]

四、总结一下

总的来说是一个不痛不痒的新特性,你学到了,下面总结一下

  1. details通常和summary配合使用,天然支持展开收起的效果
  2. summary前面的黑色三角形是::marker渲染的,可以通过设置list-style: none去除
  3. 新增的name属性可以直接通过dom.name的方式设置和获取
  4. 多个details元素添加name属性后会变成手风琴模式,即打开其中一个会关闭其他
  5. 目前兼容性还不行,需要polyfill一下
  6. 可以通过'name' in document.createElement('details')来检测是否支持该特性
责任编辑:武晓燕 来源: 前端侦探
相关推荐

2012-08-22 10:28:03

jQuery

2012-05-09 13:45:04

jQuery

2023-01-30 14:09:51

物联网网络存储

2023-09-21 10:09:10

JavaScript数组分组

2023-08-29 09:43:21

Node.js.env

2023-09-13 11:58:17

云原生反模式

2020-11-09 14:41:58

iOS 14.2苹果JIT

2015-04-15 13:33:23

2011-02-24 10:23:46

FireFTP

2019-04-25 11:02:43

Chrome浏览器Windows 10

2023-08-16 15:30:32

Windows 11微软

2021-07-13 07:52:03

云原生弹性模式

2023-07-13 15:24:13

云计算云原生架构

2010-08-23 09:23:49

Windows Pho

2009-06-03 08:50:03

微软Windows 7操作系统

2022-07-07 08:30:50

类型注解原生JS

2022-04-06 08:19:13

Go语言切片

2017-08-08 11:18:26

AndroidIntent原生

2009-02-27 09:41:15

Windows 7微软mov文件

2014-03-11 10:03:25

设计模式
点赞
收藏

51CTO技术栈公众号