本文利用的是HTML5 details, summaryjavascript
首先前端
1、了解HTML5 details, summary默认交互行为java
<details>
标签在Chrome,Firefox等浏览器下默认是有展开收起行为的,例以下面HTML:web
<details>
<summary>这是摘要1</summary>
<p>这里具体描述,标签相对随意,例如这里使用的<p>标签。</p>
</details>
复制代码
结果UI表现为:浏览器
具体描述为:bash
<summary>
标签内容,而<p>
默认隐藏了;<summary>
标签前面出现了一个小三角;小三角图形的隐喻是:我是可点击的,点击我可能会出现宝箱。框架
OK,咱们不妨就点击一下,结果以下图:ide
具体描述为:svg
<p>
标签显示出来了;<summary>
标签前面的小三角方向朝下了;此时咱们再一次点击,<p>
标签内容又会隐藏收起,箭头方向还原,以下图:学习
活脱脱一个自然的展开收起效果。
经过在<details>
标签上添加布尔类型的open
属性,可让咱们的详情信息默认就是展开状态,以下HTML示意:
<details open>
<summary>这是摘要2</summary>
<content>这里<details>标签设置了HTML布尔属性open,所以,默认是展开状态。</content>
</details>
复制代码
结果以下截图:
若是咱们使用JS脚本手动移除这个open
属性,即便没有点击行为的发生,咱们内容也会收起。
<summary>
标签若是缺省,则<details>
元素会在内部自动建立一个<summary>
内容,默认的文案是“详细信息”。以下HTML代码:
<details open>
<p>若是<summary>缺省,则会自动补上,文案是“详细信息”。</p>
</details>
复制代码
结果以下截图所示:
2、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>
复制代码
UI能够定制了,可是还有个不容忽视的体验问题,那就是在Chrome浏览器下点击时候会出现outline
轮廓,以下图所示:
在实际项目开发的时候,产品和设计必定会让你把这个效果去掉的。以及,当咱们<summary>
元素点击较快的时候,文本会被选中,也不是咱们想看到的。
阻止文本选中,咱们能够:
summary {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
复制代码
对于outline轮廓,比较直接的作法是:
summary {
outline: 0;
}
复制代码
可是这样处理对无障碍访问而是很是不友好的,那有没有什么办法兼顾视觉体验和无障碍访问体验呢?
个人作法是这样子的:
<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>
元素内的内容信息不断的展开与收起:
而后上面实现并不完美,相比原生的
对于标签,其浏览器行为只能经过回车键触发,空格键是无效的;可是对于
若是想要同时支持回车键展开与收起,能够对HTML以下处理:
<details open>
<summary tabindex="-1"><a href="javascript:" onClick="this.parentNode.click();">这是示例</a></summary>
<content>点击无外框,键盘focus有。</content>
</details>
复制代码
须要注意的是上面处理在
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复制到页面中,视觉体验和交互体验完美支持的
表现为,点击
例以下图就是键盘Tab键focus
后回车后的效果:
往往看到如此极致的用户体验处理,心情都大好。
原理: 关键是全局监听keydown
事件,若是有发生,则认为此100毫秒内的页面focus
行为均是键盘产生,从而有效区分是点击触发的focus
行为仍是键盘触发的focus
行为,若是是键盘触发,给<summary>
元素手动增长outline
效果。
了解了<details>
元素的点击交互行为;解决了UI定制难题;解决了outline
的体验问题,下面咱们就能够付诸实践,不借助任何JS来实现各类咱们日常见到的交互效果。
实现最终效果以下gif:
由于“更多”元素是在底部,所以效果实现的要点的全部的内容信息都放在<summary>
元素内部,而后经过<details>
元素的open
属性控制UI的变化。
HTML和CSS代码以下,其中,最核心部分已经红色高亮:
<details>
<summary>
<p>据台媒报道,大...青睐。</p>
<div class="more">
<p>其余几首歌曲...</p>
</div>
<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]属性选择器控制器显示,效果即达成。
效果以下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>
元素内置行为就搞定了。
此效果常见于条目比较多的垂直导航栏,新闻条目等。
例以下面实现的效果:
这个更加简单了,就是一堆<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技术就能够效果达成。
这里的树形菜单效果实现也很简单,多个<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;
}
复制代码
效果即达成!
5、若是只想要details/summary的语义不要行为
若是只想要<details>
元素,<summary>
元素的语义,可是并不须要点击展开收起的行为,该怎么处理呢?
例如,某评论,或者某帖子有标题和正文,很是符合详情-概要-内容的语义,可是但愿是纯展现的,点击时候不收起,能够这么处理:
1.<summary>
标签设置tabindex="-1"让键盘没法访问; 2.设置CSS:
summary {
outline: 0;
pointer-events: none;
}
复制代码
这样就不能点,也不会有outline轮廓。
兼容性以下图:
除了IE和Edge浏览器,大好河山一片绿,至少移动端能够用得比较开心。
若是想要在桌面web网页使用<details>
元素的棒棒哒特性,咱们能够对其进行Polyfill
对键盘访问,事件toggle都作了兼容。
若是开发策略是对不支持的IE进行特异处理,则下面的JS判断是否支持<details>
元素的脚本可能对你有用:
var isSupportDetails = 'open' in document.createElement('details');
最后,无JS实现的好处有:
省了代码,加载快了; 实现更简单了,开发快了; JS还没加载交互也能进行,体验好了; 键盘无障碍和aria阅读设备无障碍自然支持,体验档次高了。
这里推荐一下个人前端学习交流群:784783012 ,里面都是学习前端的,若是你想制做酷炫的网页,想学习知识。本身整理了一份2018最全面前端学习资料,从最基础的HTML+CSS+JS到移动端HTML5到各类框架的学习资料都有整理,送给每一位前端小伙伴,有想学习web前端的,或是转行,或是大学生,还有工做中想提高本身能力的,正在学习的小伙伴欢迎加入学习。