惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
V
V2EX
博客园_首页
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Recent Announcements
Recent Announcements
博客园 - 司徒正美
Microsoft Security Blog
Microsoft Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Latest news
Latest news
Vercel News
Vercel News
The Register - Security
The Register - Security
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
N
Netflix TechBlog - Medium
WordPress大学
WordPress大学
小众软件
小众软件
L
Lohrmann on Cybersecurity
GbyAI
GbyAI
P
Privacy & Cybersecurity Law Blog
T
Tor Project blog
AWS News Blog
AWS News Blog
美团技术团队
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
K
Kaspersky official blog
B
Blog RSS Feed
G
Google Developers Blog
量子位
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
Scott Helme
Scott Helme
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
Intezer
雷峰网
雷峰网
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Blog — PlanetScale
Blog — PlanetScale
IT之家
IT之家
F
Full Disclosure
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 【当耐特】
The Hacker News
The Hacker News
U
Unit 42
S
SegmentFault 最新的问题
I
InfoQ
aimingoo的专栏
aimingoo的专栏
Y
Y Combinator Blog
宝玉的分享
宝玉的分享
罗磊的独立博客
Spread Privacy
Spread Privacy
C
CERT Recently Published Vulnerability Notes

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活 翻译 – CSS Sprites:实用技术还是生厌之物? « 张鑫旭-鑫空间-鑫生活 纯CSS实现易拉罐3D滚动效果 « 张鑫旭-鑫空间-鑫生活 纯CSS实现侧边栏/分栏高度自动相等 « 张鑫旭-鑫空间-鑫生活 CSS+JavaScript实现页面不同布局的切换 « 张鑫旭-鑫空间-鑫生活 JavaScript实现最简单的拖拽效果 « 张鑫旭-鑫空间-鑫生活 自己写的无图片版jQuery zxxbox弹出框插件 « 张鑫旭-鑫空间-鑫生活 中国古代道家思想与网页重构的思考 « 张鑫旭-鑫空间-鑫生活 让所有浏览器支持HTML5 video视频标签 « 张鑫旭-鑫空间-鑫生活 纯CSS实现各类气球泡泡对话框效果 « 张鑫旭-鑫空间-鑫生活 JS HEX十六进制与RGB, HSL颜色的相互转换 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变、高光等文字效果 « 张鑫旭-鑫空间-鑫生活 去除冗余 – 精简您的CSS样式代码 « 张鑫旭-鑫空间-鑫生活 对overflow与zoom”清除浮动”的一些认识 « 张鑫旭-鑫空间-鑫生活 jQuery Pagination Ajax分页插件中文详解 « 张鑫旭-鑫空间-鑫生活 absolute绝对定位的非绝对定位用法 « 张鑫旭-鑫空间-鑫生活 网页布局思想浅议-淘宝新版首页为实例 « 张鑫旭-鑫空间-鑫生活 回流与重绘:CSS性能让JavaScript变慢? « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(二) « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(一) « 张鑫旭-鑫空间-鑫生活 60个极富创造性的震撼的电影海报设计 « 张鑫旭-鑫空间-鑫生活 jQuery Lightbox(balupton版)图片展示插件讲解 « 张鑫旭-鑫空间-鑫生活 博客内嵌flash音乐播放器代码、下载与使用 « 张鑫旭-鑫空间-鑫生活 CSS3 animate实现图片墙3D翻转效果 « 张鑫旭-鑫空间-鑫生活 图片旋转效果的一些研究、jQuery插件及实例 « 张鑫旭-鑫空间-鑫生活 CSS3 border-image详解、应用及jQuery插件 « 张鑫旭-鑫空间-鑫生活 jQuery-两款不同原理的圆角插件讲解 « 张鑫旭-鑫空间-鑫生活 页面可用性之outline轮廓外框的一些研究 « 张鑫旭-鑫空间-鑫生活 CSS3 transition实现超酷图片墙动画效果 « 张鑫旭-鑫空间-鑫生活 HTML CSS列表元素ul,ol,dl的研究与应用 « 张鑫旭-鑫空间-鑫生活 jQuery图片文本滚动切换插件jCarousel中文翻译与详解 « 张鑫旭-鑫空间-鑫生活 酷酷的jQuery鼠标悬停图片放大切换显示效果 « 张鑫旭-鑫空间-鑫生活 IE6下z-index犯癫不起作用bug的初步研究 « 张鑫旭-鑫空间-鑫生活 checkbox复选框的一些深入研究与理解 « 张鑫旭-鑫空间-鑫生活 jQuery之使用slideToggle实现垂直下拉菜单 « 张鑫旭-鑫空间-鑫生活 jQuery-innerfade内部列表自动淡入淡出插件 « 张鑫旭-鑫空间-鑫生活 jQuery-火焰灯效果导航菜单 « 张鑫旭-鑫空间-鑫生活 IE下css bug集合-翻译自haslayout.net « 张鑫旭-鑫空间-鑫生活 翻译-IE7/8@font-face嵌入字体与文字平滑 « 张鑫旭-鑫空间-鑫生活 jQuery-马化腾产品设计与用户体验的一些技术实现 « 张鑫旭-鑫空间-鑫生活 像素的世界及其在web开发制作中的应用 « 张鑫旭-鑫空间-鑫生活 css行高line-height的一些深入理解及应用 « 张鑫旭-鑫空间-鑫生活 CSS实现圆角六色渐变自适应按钮详解 « 张鑫旭-鑫空间-鑫生活 我熟知的三种三栏网页宽度自适应布局方法 « 张鑫旭-鑫空间-鑫生活 jQuery照片图像剪裁插件Jcrop中文翻译详解 « 张鑫旭-鑫空间-鑫生活 Ajax Upload多文件上传插件翻译及中文演示 « 张鑫旭-鑫空间-鑫生活 告别图片—使用字符实现兼容性的圆角尖角效果beta版 « 张鑫旭-鑫空间-鑫生活 大小不固定的图片、多行文字的水平垂直居中 « 张鑫旭-鑫空间-鑫生活 jQuery boxy弹出层对话框插件中文演示及讲解 « 张鑫旭-鑫空间-鑫生活 JavaScript实现新浪微博文字放大显示动画效果 « 张鑫旭-鑫空间-鑫生活 翻译:让网络更快一些——最小化浏览器中的回流(reflow) « 张鑫旭-鑫空间-鑫生活 jQuery之addClasas与removeClass使用实例 « 张鑫旭-鑫空间-鑫生活 关于Google圆角高光高宽自适应按钮及其拓展 « 张鑫旭-鑫空间-鑫生活 JavaScript实现图片幻灯片滚动播放动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery-鼠标经过显示大图并跟随鼠标效果插件 « 张鑫旭-鑫空间-鑫生活 关于gif图片(或png8)杂边锯齿的问题 « 张鑫旭-鑫空间-鑫生活 对html与body的一些研究与理解 « 张鑫旭-鑫空间-鑫生活 鲜为人知的一个解决兼容性问题的利器——小数 « 张鑫旭-鑫空间-鑫生活 搜狐白社会似iphone短信对话框效果的优化 « 张鑫旭-鑫空间-鑫生活 关于文字内容溢出用点点点(…)省略号表示 « 张鑫旭-鑫空间-鑫生活 jquery之append与insertBefore使用实例 « 张鑫旭-鑫空间-鑫生活 jQuery之图片关联伸缩效果 « 张鑫旭-鑫空间-鑫生活 jquery之图片左右切换动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery之replace字符串替换实现不同尺寸图片切换 « 张鑫旭-鑫空间-鑫生活 jQuery-实现图片的放大镜显示效果 « 张鑫旭-鑫空间-鑫生活 jQuery-单击文字或图片内容放大显示效果插件 « 张鑫旭-鑫空间-鑫生活 reflection.js-实现图片投影倒影效果js插件 « 张鑫旭-鑫空间-鑫生活 jQuery-很酷的弹出层效果js插件 « 张鑫旭-鑫空间-鑫生活 复选框单选框与文字对齐问题的研究与解决 « 张鑫旭-鑫空间-鑫生活 css margin的相关属性,问题及应用 « 张鑫旭-鑫空间-鑫生活 IE6下png背景不透明问题的综合拓展 « 张鑫旭-鑫空间-鑫生活
突发奇想,同步单复选框checked态岂不点击通杀? « 张鑫旭-鑫空间-鑫生活
张鑫旭,zhangxinxu · 2020-11-26 · via 张鑫旭-鑫空间-鑫生活

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9683
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

思考的狐狸,突发奇想的张鑫旭

标题完整内容应该是“就在星期天的下午,我在书房突发奇想,要是可以让元素(如<label>元素)无论在页面什么位置都能响应单选框或复选框元素的状态变化,那么几乎页面所有的点击交互岂不是都可以通杀了,那就牛逼大啦!”

到底牛不牛逼呢,大家可以跟过来一起看看评一评。

一、起步、背景和目标效果

几乎所有常见的点击交互的本质就是单选或者复选。

例如选项卡是典型的单选,展开收起或者下拉就是典型的复选(只有1个选项的复选),树结构是多选等。

因此radio/checkbox配合:checked伪类可以纯CSS实现大量的点击交互效果,这个技术我早在8年前就介绍过了:“CSS radio/checkbox单复选框元素显隐技术”。

但是这个技术有个限制,由于CSS选择器中的+或者~选择符只能选择后面的兄弟元素,因此,交互事件的主体需要和单复选框元素是兄弟关系,这就导致DOM结构有了明显的限制。

有一种方法可以一定程度上绕开这种限制,就是使用<label>元素,通过for属性与单选复选元素进行关联,这样,单选框或者复选框就可以在页面的任意的位置。

但是这种方法虽然功能OK,但是DOM的结构却很奇怪,语义不符,结构混乱,例如实现选项卡效果的时候,选项卡按钮和选项卡面板元素需要公用一个祖先元素,如下截图红框框所示,这太奇怪了,完全不能用在实际项目中。

奇怪的单复选框实现效果

突发奇想的背景

我的上一篇文章就是和单选框技术相关的,实现下图这个单选变色效果:

列表点击效果

因为HTML代码有限制,如下所示:

<ul>
    <li><input type="radio" name="item" checked>选项1</li> 
    <li><input type="radio" name="item">选项2</li> 
    <li><input type="radio" name="item">选项3</li> 
    <li><input type="radio" name="item">选项4</li> 
    <li><input type="radio" name="item">选项5</li> 
</ul>

所以用了“高级的”mix-blend-mode属性实现的。

当时,我就琢磨着,要是父元素<li>可以实时响应里面单选框元素的checked状态,什么屁事都没了,关键就是不支持,毕竟CSS中没有父选择器。

心有不甘,一直盘在心里,然后周日晚上9点多的时候,看着鱼缸里的自由自在的小鱼,就突然来了灵感:嘿!以我目前的技术储备,想要让任意元素和单复选框的checked状态关联似乎是可行的呀,脑子里盘了盘,有了个雏形,然后就开始开搞。

目标效果

实现的目标效果如下:

  1. 引入一段JS代码;
  2. 任意for/id属性关联元素状态实时联动;

例如:

<ul>
    <li for="$1"><input type="radio" id="$1" name="item" checked>选项1</li> 
    <li for="$2"><input type="radio" id="$2" name="item">选项2</li> 
    <li for="$3"><input type="radio" id="$3" name="item">选项3</li> 
    <li for="$4"><input type="radio" id="$4" name="item">选项4</li> 
    <li for="$5"><input type="radio" id="$5" name="item">选项5</li> 
</ul>

无论通过何种方式改变了单选框元素的选中态,for属性值等于这个单选框元素id值的任意元素都会有对应的状态列表,例如toggle一个类名.active

这样,就可以使用li.active选择器轻松改变文字的颜色了。

二、代码出场、基本效果

按照心中的雏形,盘啊盘,测啊测,代码撸出来了。

该JS地址为:smart-for.js

直接在页面中引入下面的JS,然后万能点击效果就有了。

<script src="smart-for.js"></script>

眼见为实,上面那个列表选择效果,您可以狠狠地点击这里:父元素响应单选框checked状态demo

打开控制台,就可以看到,单选框在点击的时候,父元素的类名.active会自动添加删除。

类名自动同步示意

状态关联的机制很简单,就是需要状态同步的元素的for属性值就是单选框或复选框元素的id属性值就可以了,类似于<label>元素和单复选框元素的关联。

有了smart-for.js,几乎所有的点击交互效果就不需要额外的JS代码去实现了,通杀。

popup或侧边栏效果

例如移动端常见的底部popup浮层效果,或者aside侧边栏效果,就不需要额外的JS来实现了。

眼见为实,您可以狠狠地点击这里:无业务JS实现的Popup和Aside浮层交互demo

可以看到如下GIF所示的效果(点击播放-183K):

浮层出现隐藏效果示意

相关代码如下,主要是HTML部分,侧边栏效果示意,无关紧要代码删除了:

<label class="ui-button"><input type="checkbox" id="zxxAside" hidden>点击我显示侧边栏</label>
<aside class="aside" for="zxxAside">
    <label for="zxxAside" class="aside-overlay"></label>
    <div class="aside-content">点击黑色蒙层可以收起</div>
</aside>

显隐控制的CSS代码主要就是:

.aside {
    visibility: hidden;
}
.aside.active {
    visibility: visible;
}

浏览器有个特性,点击<label>元素,里面的单选框或者复选框元素就会选中,此时就会触发任意for="zxxAside"的元素添加类名.active,于是浮层显示。

黑色蒙层使用的是指向复选框的<label>元素,因此点击时候就会取消复选框的选中,此时<aside>元素的.active类名自动删除,浮层隐藏。

如果希望点击其他元素或者按钮让隐藏,但是又不想使用<label>元素。

则需要使用JS改变复选框元素的选中态,例如:

someEle.addEventListener('click', function () {
    zxxAside.checked = false;
});

元素状态会自动同步,无需开发者去触发。

展开更多效果

这个demo页面是老的:checked伪类实现的效果,不过需要固定的层级,有了本文的JS代码,可以无视层级,更自由了,实现自然不在话下。

例子就不举了,因为这种交互更推荐使用“<details>、<summary>元素实现”,纯CSS,语义更好,不支持的浏览器简单几行JS Polyfill下就可以了。

更多展开收起gif效果

//zxx: 如果你看到这段文字,说明你现在访问是体验糟糕的垃圾盗版网站,你可以访问原文获得很好的体验:https://www.zhangxinxu.com/wordpress/?p=9683(作者张鑫旭)

下拉列表效果

这个效果绝对是CSS :focus-within伪类实现最佳,纯CSS,现代浏览器兼容性还是可以的,我已经在实际项目中使用了,Safari浏览器注意使用<a>元素+tabindex="0"

<details>/<summary>元素也可以实现下拉列表效果,本文的checked状态同步也可以实现,但是,点击空白区域隐藏这个处理,在复杂页面场景下可能会有层级混乱的问题。

算了,想了想,还是整个demo吧,万一可以帮到需要的人呢,毕竟兼容性要比:focus-within伪类好很多,IE11+都支持。

您可以狠狠地点击这里:checked状态同步与下拉列表交互demo

下面的GIF录屏就是demo页面实现的交互效果:

checked状态实现的下拉列表效果GIF

优点除了兼容性好之外,还有就是下拉列表浮层元素的位置是可以任意的。其他几个CSS方法都有DOM位置和层级的限制。

大家有兴趣可以研究下demo页面中的源代码。

选项卡切换效果

有了本文的smart-for.js,选项卡效果再也不需要复杂而又奇怪的DOM层级结构了。

您可以狠狠地点击这里:checked状态同步选项卡效果demo (内有完整的源代码)

此时的HTML结构就是正常的了,符合我们的理解和认知:

正常选项卡结构示意

实现效果如下GIF所示:

选项卡切换效果GIF录屏

更多细节参见demo页面,这里不展开。


总之,只要引入一小段JS代码,Min + Gzip后 < 1K,借助隐藏的单选框或者复选框元素,各类点击交互效果就无需额外的JS代码了,层级无限制,位置无限制,元素几乎无限制,非常灵活。

反正这年头语义化就是个梦,大家应该会用得很开心的。

三、实现的原理、难点在哪

要想让元素和单复选框元素的:checked状态关联还是有一些挑战的。

因为单复选框:checked状态变化的场景太多了:

  1. 点击行为选中(无任何属性变化)
  2. JS设置:radio.checked = true // 或false
  3. HTML属性设置:radio.setAttribute(‘checked’, ”)
  4. 单选框组中其他元素check导致自身uncheck
  5. 页面新增一个单复选框
  6. 删除一个单复选框
  7. 页面新增一个for关联元素

必须观察上面所有的场景,而且要立即识别,无需用户主动触发。

对于checked状态变化,我一开始的思路是:

:checked {
    padding: 0.1px;
}

然后使用ResizeObserver观察元素的尺寸是否变化,这样就知道状态可能发生了变化。但是这样做,需要元素非display:none隐藏,而且,最重要的是ResizeObverse iOS 13才开始支持,兼容性不佳,于是放弃了这个想法,改为采用下面的策略:

  1. dom.checked引起的状态变化通过重置单复选框元素的checked属性实现的,代码如下:
    var propsChecked = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'checked');
    var propsCheckedNew = {};
    
    for (key in propsChecked) {
        propsCheckedNew[key] = propsChecked[key];
    }
    
    propsCheckedNew.set = function (value) {
        propsChecked.set.call(this, value);
        // 同步对应label元素的状态
        funCheckedSync(this);
    };

    补充于翌日

    感谢XboxYan的反馈,观察checked状态变化还可以使用animationend回调,兼容性会好很多,IE10+,不足就是display:none隐藏无法感知。

  2. setAttribute/removeAttribute导致的属性变化、DOM元素的增删,全部使用MutationObserver方法实现,这个在之前“聊聊JS DOM变化的监听检测与应用”一文中有介绍,IE11+支持。

    具体代码这里就不展示了。

  3. 点击行为导致的状态变化采用委托的方式进行监听,代码如下:
    document.addEventListener('click', function (event) {
        var eleTarget = event && event.target;
        if (eleTarget && eleTarget.matches('[type="radio"], [type="checkbox"]')) {
            funCheckedSync(eleTarget);
        }
    });

更多细节大家仔细参阅源码。


算了算了,直接浏览器打开的代码一坨糊,很不利于阅读。

我找了个地方开源了下:https://gitee.com/zhangxinxu/smart-for

gitee速度杠杠的,比github快多了,欢迎关注我 张鑫旭https://gitee.com/zhangxinxu)。

关注我的gitee

以后非国际化的项目我都会放在gitee上,国际形势不定,放在github上的代码说不定哪天都不是自己的。

JS源码参阅直接戳这里:https://gitee.com/zhangxinxu/smart-for/blob/master/smart-for.js

吼吼~

四、测试、降维打击、结语

为了验证品质,我还专门写了个测试页面

点击测试按钮,一排绿的感觉真好,然后有改动,测一下,也放心一点。

理论上,IE9+浏览器也是可以对DOM和属性进行观察的,但是那几个window事件性能太差,早就要淘汰了,我就没支持。

因此,本JS兼容到IE11+,也就是MutationObserver方法支持的版本。

例如下图是IE11浏览器下的测试结果:

IE11下测试结果示意

降维打击

本文的这个JS覆盖点击交互的方法,感觉就是一个完全的不同层面的思路,有种降维打击的感觉。

无需针对每一种交互效果去写具体的代码,只要抽象出一个规则,然后利用浏览器原生的特性,配合已知的一些浏览器API能力,就可以实现全覆盖的交互增强支持。

根据这么多年的时间,单选复选的浏览器原生特性是非常稳健的,因此,代码出坑的可能性并不大。

以后要是有个运营活动之类的项目、或者内部项目,我会尝试用用看,感受下到底香不香。

OK,以上就是本文的全部内容,周末突然的一点奇思妙想,居然扯这么多内容。

研究、学习、成长不止!

感谢您的阅读,如果你觉得本文内容还不错,欢迎转发。

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=9683

(本篇完)