您好,欢迎访问一九零五行业门户网

利用HTML5的details, summary实现各种交互效果

本篇文章给大家带来的内容是关于利用html5的details, summary实现各种交互效果,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
本文利用的是html5 details, summary
首先
一、了解html5 details, summary默认交互行为
<details> 标签在chrome,firefox等浏览器下默认是有展开收起行为的,例如下面html:
<details>    <summary>这是摘要1</summary>    <p>这里具体描述,标签相对随意,例如这里使用的<p>标签。</p></details>
结果ui表现为:
具体描述为:
1、只显示了<summary>标签内容,而<p>默认隐藏了;
2、<summary>标签前面出现了一个小三角;
小三角图形的隐喻是:我是可点击的,点击我可能会出现宝箱。
ok,我们不妨就点击一下,结果如下图:
具体描述为:
原本隐藏的<p>标签显示出来了;
<summary>标签前面的小三角方向朝下了;
此时我们再一次点击,<p>标签内容又会隐藏收起,箭头方向还原,如下图:
活脱脱一个天然的展开收起效果。
展开与收起是通过open属性控制的通过在<details>标签上添加布尔类型的open属性,可以让我们的详情信息默认就是展开状态,如下html示意:
<details open>    <summary>这是摘要2</summary>    <content>这里<details>标签设置了html布尔属性open,因此,默认是展开状态。</content></details>
结果如下截图:
如果我们使用js脚本手动移除这个open属性,即使没有点击行为的发生,我们内容也会收起。
<summary>如果缺省<summary>标签如果缺省,则<details>元素会在内部自动创建一个<summary>内容,默认的文案是“详细信息”。如下html代码:
<details open>    <p>如果<summary>缺省,则会自动补上,文案是“详细信息”。</p></details>
结果如下截图所示:
二、details浏览器内置ui可以自定义
<details>标签默认的小三角样式有些简陋,在实际应用的时候,往往不是我们希望的样子,不要担心,我们是可以对其进行自定义的。在chrome等浏览器下使用::-webkit-details-marker,在firefox浏览器下使用::-moz-list-bullet可以对小三角进行ui控制,例如改变颜色,改变大小,使用自定义的图形代替,或者直接隐藏等,我们来看几个简单的案例。
案例1:小三角右侧显示同时颜色变淡
html代码如下:
<details class="details-1" open>    <summary>这是示例1</summary>    <content>本案例展示对小三角ui重定义:包括显示在右侧,颜色减淡等。</content></details>
css如下:
.details-1 summary {    width: -moz-fit-content;    width: fit-content;    direction: rtl;}.details-1 ::-webkit-details-marker {    direction: ltr;    color: gray;    margin-left: .5ch;}.details-1 ::-moz-list-bullet {    direction: ltr;    color: gray;    margin-left: .5ch;}
结果如下图所示:
当我们点击摘要标题升起的时候,表现为下图(截自firefox):
而实际上实际开发的时候,对小三角ui更便捷的定制方法是:隐藏浏览器原生的小三角,然后借助::before或::after伪元素重新生成我们想要的ui效果,下面这个案例就将展示相关的处理。
案例2:隐藏浏览器原生的小三角并使用自定义三角替换
html结构还是类似的:
<details class="details-2" open>    <summary>这是示例2</summary>    <content>本案例隐藏原生小三角,使用自定义小三角。</content></details>
css主要分为2部分,一部分是隐藏浏览器原生的小三角,另外一部分是使用伪元素生成自定义的三角效果。
首先看一下隐藏<details>标签默认的小三角的css:
/* 隐藏默认三角 */.details-2 ::-webkit-details-marker {    display: none;}.details-2 ::-moz-list-bullet {    font-size: 0;}
可以看到chrome浏览器和firefox浏览器的小三角隐藏采用的是不同的策略。在chrome浏览器下,我们可以直接设置display:none进行隐藏,但是这一招在firefox浏览器下确实没有效果的,即使设置display:none!important也是如此,根据我的测试,只有font-size:0能够比较完美的隐藏。类似position:absolute;visibility:hidden这种常见的隐藏也是不行的,因为position:absolute无法生效。
然后是自定义小三角显示的css,这里采用的是::after伪元素模拟的:
/* 自定义的三角 */.details-2 summary::after {    content: '';    position: absolute;    width: 1em; height: 1em;    margin: .2em 0 0 .5ch;    background: url(./arrow-on.svg) no-repeat;    background-size: 100% 100%;    transition: transform .2s;}.details-2:not([open]) summary::after {    margin-top: .25em;    transform: rotate(90deg);    }
最终效果如下图所示:
收起时候:
最后有一点需要注意一下,就是如果<details>标签内并没有<summary>元素,则我们的对三角的自定义代码都是无效的,可以使用一个空的<summary>元素占位,类似这样:
<details>    <summary></summary>    <content>内容。</content></details>
三、chrome浏览器下点击时候outline轮廓等体验处理
ui可以定制了,但是还有个不容忽视的体验问题,那就是在chrome浏览器下点击时候会出现outline轮廓,如下图所示:
在实际项目开发的时候,产品和设计一定会让你把这个效果去掉的。以及,当我们<summary>元素点击较快的时候,文本会被选中,也不是我们想看到的。
阻止文本选中,我们可以:
summary {  -webkit-user-select: none;  -moz-user-select: none;  -ms-user-select: none;  user-select: none;}
对于outline轮廓,比较直接的做法是:
summary {  outline: 0;}
但是这样处理对无障碍访问而是非常不友好的,那有没有什么办法兼顾视觉体验和无障碍访问体验呢?
我的做法是这样子的:
利用<a>标签的outline交互体验
浏览器对<a>标签元素的outline轮廓进行了专门的体验优化处理,鼠标点击的时候不显示轮廓,键盘访问时候显示轮廓。于是我们可采用李代桃僵策略,让<summary>元素的outline交给<a>元素,方法就是在<summary>中再内嵌一个<a>,同时通过tabindex属性remove掉<summary>原本的可访问性。html代码示意如下:
<details open>    <summary tabindex="-1"><a href="javascript:">这是示例</a></summary>    <content>点击无外框,键盘focus有。</content></details>
css如下:
summary {    user-select: none;    outline: 0;}summary a {    color: inherit;}
此时,在chrome浏览器下,我们点击摘要信息,没有任何outline轮廓出现;但是当我们使用tab键索引时候,可以看到下图所示的轮廓效果:
轮廓区域比原生的<summary>要小,但这无伤大雅,而且实际项目开发的时候,我们会去掉小箭头,此时只要设置<a>标签display:block,则轮廓就可以和<summary>保持一致了。
接下来,我们按下space空格键,就会发现<details>元素内的内容信息不断的展开与收起:
然后上面实现并不完美,相比原生的<summary>元素,enter回车键展开收起效果丢失了。这是因为html元素中如果多个focusable同时带click浏览器行为元素嵌套的时候,点击里面的元素,外部元素的浏览器行为是不会触发的。类似的有<label>内嵌<a>标签。
对于<a>标签,其浏览器行为只能通过回车键触发,空格键是无效的;但是对于<summary>,回车键和空格键都能触发展开收起行为,这就是为什么上面代码空格键有效,回车键无效的原因。
如果想要同时支持回车键展开与收起,可以对html如下处理:
<details open>    <summary tabindex="-1"><a href="javascript:" onclick="this.parentnode.click();">这是示例</a></summary>    <content>点击无外框,键盘focus有。</content></details>
需要注意的是上面处理在<summary>自己额外绑定click事件时候可能会有double触发的问题,此时,阻止<a>元素的冒泡即可。
js捕获键盘行为手动设置outline
这个方法不需要对html进行任何的改动,是通过css和js配合对全局的<summary>元素进行outline优化。
css如下:
summary {    user-select: none;    outline: 0;}summary[focus] {    outline: 1px dotted;    outline: 5px auto -webkit-focus-ring-color;}
js如下:
window.addeventlistener('keydown', function () {        window.iskeyevent = true;    settimeout(function () {        window.iskeyevent = false;    }, 100);    });document.addeventlistener('focusin', function (event) {    var target = event.target;    if (target && target.tagname.tolowercase() == 'summary' && window.iskeyevent == true) {        target.setattribute('focus', '');    }});document.addeventlistener('focusout', function (event) {    var elefocusall = document.queryselectorall('summary[focus]');    [].slice.call(elefocusall).foreach(function (summary) {        summary.removeattribute('focus');    });});
只要把上面的css和js复制到页面中,视觉体验和交互体验完美支持的<summary>元素outline效果就有了。
表现为,点击<summary>没有任何outline,键盘focus时候出现,且和浏览器原生outline效果一模一样,space键和enter键展开与收起访问完全保留。
例如下图就是键盘tab键focus后回车后的效果:
每每看到如此极致的用户体验处理,心情都大好。
原理:
关键是全局监听keydown事件,如果有发生,则认为此100毫秒内的页面focus行为均是键盘产生,从而有效区分是点击触发的focus行为还是键盘触发的focus行为,如果是键盘触发,给<summary>元素手动增加outline效果。
四、基于details元素行为的各种交互效果案例
了解了<details>元素的点击交互行为;解决了ui定制难题;解决了outline的体验问题,下面我们就可以付诸实践,不借助任何js来实现各种我们平常见到的交互效果。
案例1:“更多”展开与收起效果实现最终效果如下gif:
因为“更多”元素是在底部,因此效果实现的要点的所有的内容信息都放在<summary>元素内部,然后通过<details>元素的open属性控制ui的变化。
html和css代码如下,其中,最核心部分已经红色高亮:
<details>    <summary>        <p>据台媒报道,大...青睐。</p>        <p class="more">            <p>其他几首歌曲...</p>        </p>        <a>更多</a>    </summary> </details>::-webkit-details-marker {    display: none;}::-moz-list-bullet {    font-size: 0;    float: left;}.more {    display: none;}[open] .more {    display: block;}[open] summary a {    font-size: 0;}[open] summary a::before {    content: '收起';    font-size: 14px;}
把“更多”对应的信息放在.more元素内,然后通过[open]属性选择器控制器显示,效果即达成。
案例2:无js实现点击显示悬浮菜单,自定义下拉框等效果效果如下gif:
没有任何js参与。html结构如下:
<details>    <summary>我的消息</summary>     <div class="box">        <a href>我的回答<sup>12</sup></a>        <a href>我的私信</a>        <a href>未评价订单<sup>2</sup></a>        <a href>我的关注</a>    </div></details>
然后css让.box元素绝对定位即可,显示和隐藏<details>元素内置行为就搞定了。
案例3:accordion多项折叠效果此效果常见于条目比较多的垂直导航栏,新闻条目等。
例如下面实现的效果:
这个更加简单了,就是一堆<details>元素并排放置就可以了,如下html:
<details open>    <summary><dt>订单中心</dt></summary>     <dd><a href>我的订单</a></dd>    <dd><a href>我的活动</a></dd>    <dd><a href>评价晒单</a></dd>    <dd><a href>购物助手</a></dd></details><details open>    <summary><dt>关注中心</dt></summary>     <dd><a href>关注的商品</a></dd>    ...</details><details open>    ...</details>
计算css没有任何设置,效果也天然达成。
案例3中的展开项显示的时候是非常生硬的突然显示,实际上我们可以借助一些选择器技巧以及css3 transition属性让菜单展开收起的时候是有动画效果的,效果如下gif截图:
此效果实现原理核心是[open]属性选择器,和加号+相邻兄弟选择器。
首先看下html,展开列表结构发生了变化,不是作为<details>的子元素,而是作为其相邻兄弟元素存在,html示意:
<details open><summary>订单中心</summary></details><dl>    <dd><a href>我的订单</a></dd>    <dd><a href>我的活动</a></dd>    <dd><a href>评价晒单</a></dd>    <dd><a href>购物助手</a></dd></dl>...
上面<dl>定义列表就是展开收起的内容,其作为兄弟元素和<details>元素平起平坐,于是,我们就可以利用点击<summary>元素<details>元素的open属性会变化的特性实现我们想要的动画效果,css如下:
details + dl {    max-height: 0;    transition: max-height .25s;    overflow: hidden;}[open] + dl {    max-height: 100px;}
借助相邻兄弟选择器以及max-height任意元素slideup/slidedown技术就可以效果达成。
案例5:多级嵌套的树形菜单交互效果这里的树形菜单效果实现也很简单,多个<details>元素相互嵌套就可以,效果gif如下:
html结构大致如下:
<details>    <summary>我的视频</summary>    <details>        <summary>爆肝工程师的异世界狂想曲</summary>        <div>tv1-720p.mp4</div>        <div>tv2-720p.mp4</div>        ...        <div>tv10-720p.mp4</div>    </details>    <details>        <summary>七大罪</summary>        <div>七大罪b站00合集.mp4</div>    </details>    <div>珍藏动漫网盘地址.txt</div>    <div>我们的小美好.mp4</div></details>
css的主要工作就是绘制菜单前面的加号和减号图形,例如我们可以借助background线性渐变,相关css如下:
details {    padding-left: 20px;}summary::before {    content: '';    display: inline-block;    width: 12px; height: 12px;    border: 1px solid #999;    background: linear-gradient(to right, #999, #999) no-repeat center, linear-gradient(to top, #999, #999) no-repeat center;    background-size: 2px 10px, 10px 2px;    vertical-align: -2px;    margin-right: 6px;    margin-left: -20px;}[open] > summary::before {    background: linear-gradient(to right, #999, #999) no-repeat center;    background-size: 10px 2px;}
效果即达成!
五、如果只想要details/summary的语义不要行为
如果只想要<details>元素,<summary>元素的语义,但是并不需要点击展开收起的行为,该怎么处理呢?
例如,某评论,或者某帖子有标题和正文,非常符合详情-概要-内容的语义,但是希望是纯展示的,点击时候不收起,可以这么处理:
1.<summary>标签设置tabindex=-1让键盘无法访问;
2.设置css:
summary {  outline: 0;  pointer-events: none;}
这样就不能点,也不会有outline轮廓。
六、兼容性以及polyfill
兼容性如下图:
除了ie和edge浏览器,大好河山一片绿,至少移动端可以用得比较开心。
如果想要在桌面web网页使用<details>元素的棒棒哒特性,我们可以对其进行polyfill
对键盘访问,事件toggle都做了兼容。
如果开发策略是对不支持的ie进行特异处理,则下面的js判断是否支持<details>元素的脚本可能对你有用:
var issupportdetails = 'open' in document.createelement('details');
最后,无js实现的好处有:
省了代码,加载快了;
实现更简单了,开发快了;
js还没加载交互也能进行,体验好了;
键盘无障碍和aria阅读设备无障碍天然支持,体验档次高了。
以上就是利用html5的details, summary实现各种交互效果的详细内容。
其它类似信息

推荐信息