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

推荐订阅源

雷峰网
雷峰网
L
LangChain Blog
GbyAI
GbyAI
F
Fortinet All Blogs
腾讯CDC
Last Week in AI
Last Week in AI
A
About on SuperTechFans
J
Java Code Geeks
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - Franky
B
Blog
D
Docker
G
Google Developers Blog
月光博客
月光博客
博客园 - 三生石上(FineUI控件)
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
酷 壳 – CoolShell
酷 壳 – CoolShell
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tailwind CSS Blog
宝玉的分享
宝玉的分享
U
Unit 42
Blog — PlanetScale
Blog — PlanetScale
B
Blog RSS Feed

张鑫旭-鑫空间-鑫生活

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各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活
时代变了,该使用原生popover属性模拟下拉了 « 张鑫旭-鑫空...
张鑫旭,zhangxinxu · 2024-01-11 · via 张鑫旭-鑫空间-鑫生活

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

封面图

一、事务繁忙,长话短说

目前主流的下拉列表,或者下拉面板的实现方式都是这样的。

点击按钮,让下拉元素显示,绝对定位,同时设置层级,点击空白处,隐藏下拉列表。

其中,每一步都需要JavaScript代码的参与,因此,一个下拉组件的JS代码量还是不容小觑的。

现在,浏览器已经支持原生popover属性,上面这种下拉列表实现方式可以扫进垃圾箱了。我可以这么说,日后使用popover属性实现下拉效果一定是主流实现方案。

因为有两个好处:

  1. 代码极简;
  2. 层级顶级;

例如有如下所示的HTML代码:

<button popovertarget="imgBook">点击显示图片</button>
<img id="imgBook" popover src="/study/202312/book1.jpg" />

无需任何JS代码,点击按钮,就可以让图片显示,点击页面空白处,图片会自动隐藏,实时效果如下:


这就是上面说到的代码极简。

至于层级顶级。

这是Web中专有的一个概念,称为top-layer,元素全屏,或者<dialog>对话框使用showModal()方法显示的时候,都会表现为top-layer,如下图所示:

#top-layer示意

顾名思意就是层级顶级,页面中任何元素都无法覆盖,哪怕z-index设置为999999。

一个页面可以有多个层级顶级元素,至于哪个在最上面,采用的是后来居上的原则,也就是那个后显示,那个就在上面,这个非常符合真实的交互需求。

基于以上两点,popover属性一定是下拉交互的最佳实现。

二、案例演示,一目了然

例如,在LuLu UI中的<select>模拟下拉框的效果是这样的:

lulu ui select 模拟下拉效果

现在要实现此效果,极其简单,只需要让下拉框在显示的时候计算下定位就可以了(默认是浏览器居中定位的)。

HTML结构示意:

<button id="button" popovertarget="select">请选择</button>
<menu id="select" popover>
    <li><input type="radio" name="type" value="">请选择</li>
    <li><input type="radio" name="type" value="1">选项1</li>
    <li><input type="radio" name="type" value="2">选项2</li>
    <li><input type="radio" name="type" value="3" disabled>选项3</li>
    <li><input type="radio" name="type" value="4">选项4</li>
</menu>

使用radio单选框模拟选中行为,可以保持<select>元素的表单特性。

至于显示、隐藏以及层级设置都是popover属性自动完成的,我们无需关心,因此,所有的JS代码其实就下面这一点。

button.onclick = function () {
    const bounding = this.getBoundingClientRect();

    select.style.top = (bounding.bottom + window.pageYOffset) + 'px';
    select.style.left = (bounding.left + window.pageXOffset) + 'px';
    select.style.width = bounding.width + 'px';
};
select.onclick = function (event) {
    if (event.target.type == 'radio') {
        this.hidePopover();
        // 选择文字内容更新
        button.textContent = event.target.parentElement.textContent;
    }
}

是不是简单到瞠目结舌,匪夷所思?

眼见为实,你可以狠狠地点击这里:使用popover属性模拟select下拉demo

下拉模拟效果截图示意

下拉列表各种状态应有尽有。

三、与时俱进,勇攀高峰

popover属性目前所有现代浏览器都支持了,在不久的将来大规模应用已是大势所趋。

popover兼容性

好了,就说这么多吧。

最近忙碌,就不扯淡了。

感谢阅读,欢迎!

大人,时代变了

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

(本篇完)