欢送关注我的公众号:前端侦探

想必大家都晓得 HTML5 中有 dialog 这样一个标签,顾名思义,就是“弹窗”。除了有良好的语义外,随着浏览器的不断更新迭代,还呈现了许多你可能不晓得的个性,疾速理解一下吧~

一、关上和敞开办法

首先,在不查阅任何官网文档的状况下,先做一个抉择题目

请问:上面哪组办法(关上/敞开)是非法的?

思考 10 秒...

正确答案是 C,也就是

// 关上弹窗dialog.show()// 关上敞开dialog.close()

很多同学可能会感觉是 A 或者 B,然而官网文档上确是 C,的确是一个令人蛊惑的办法。至于起因,有解释说,dialog是存在于页面上的元素,所以关上用show,而敞开示意中断弹窗内的行为,所以用close,只能说有分割,但比拟牵强,或者就是标准设计忽略了,大家记住就好。

还有一个,如果须要弹窗默认显示,大家先猜猜看?

再来思考 10 秒...

正确答案是 B,也就是

<dialog open></dialog>

是不是又和下面的show()对不上了?

除了dialog元素,details元素的关上属性也是open

二、表单提交个性

弹窗很多时候的作用都是充当表单输出。

比方一个弹窗中须要有一个敞开或者勾销按钮

<dialog>  <h3>欢送关注前端侦探</h3>  <button>敞开</button></dialog>

通常状况下,咱们可能须要用到后面提到的dialog.close()办法来被动敞开弹窗。

其实,还能够通过表单个性实现这样一个成果,具体做法是:

  1. dialog中嵌套一层form
  2. form增加一个method=dialog属性

如下

<dialog>  <form method="dialog">    <h3>欢送关注前端侦探</h3>    <button>敞开</button>  </form></dialog>

这样就能够不必绑定额定的事件来实现敞开性能了,成果如下

其实起因就在于表单上的method=dialog属性,如果表单在dialog元素中,提交时就会触发敞开对话框

https://developer.mozilla.org...

默认状况下,表单里的button都会触发提交,等同于type=submit,但如果设置了type=button或者type=reset,则不会触发表单提交,天然也不会敞开弹窗

<dialog>  <form method="dialog">    <h3>欢送关注前端侦探</h3>    <button>敞开</button>    <button type="button">不会敞开</button>  </form></dialog>

成果如下

另外还有一个小个性,dialog还有一个returnValue属性,能够返回表单中提交按钮的value

<dialog>  <form method="dialog">    <h3>欢送关注前端侦探</h3>    <button value="AAA">提交</button>  </form></dialog>

在提交后能够打印弹窗的returnValue,如下

不过临时还没有想到很有用的场景

三、模态窗口个性

弹窗除了能够通过dialog.show()关上之外,还提供了一个模态窗口,办法是

dailog.showModal()

通过这个办法关上的弹窗,会自带一个半透明的背景,并且齐全程度垂直居中

这个半透明的背景并不是一般的元素,而是一个叫做::backdrop的伪元素管制的,并且目前只有通过dailog.showModal()这个办法能力生成

要自定义背景也很容易

dialog::backdrop {  background: rgba(255,0,0,.25);}

这样就变成了半透明红色

如果心愿关上弹窗有动画,能够自定义默认款式,通过visibility的形式实现暗藏显示

dialog{  position: fixed;  margin: auto;  inset: 0;  width: fit-content;  height: fit-content;  display: block;  visibility: hidden;  opacity: 0;  transform: translateY(100px);  transition: .2s;}dialog[open] {  visibility: visible;  opacity: 1;  transform: translateY(0);}

成果如下

其实这里我是不太倡议动画的,弹窗就是要反馈疾速,加了动画反而会连累整体。

另外,还能够通过:modal伪类来辨别是一般弹窗还是模态弹窗

dialog:modal{  /*模态弹窗*/}dialog:not(:modal){  /*一般弹窗*/}

这样能够更多进行自定义行为

模态弹窗还有一个十分省心的点,就是无需关注层级。它有一套十分直观的规定,哪个后关上,哪个层级最高,比方这样两个弹窗

<dialog id="dialog2">  ...</dialog><dialog id="dialog1">  ...  <button type="button">关上弹窗2</button>  ...</dialog>

在不指定层级的状况下,必定是前面的层级更高,但如果是通过dialog.showModal关上,就十分直观了,后关上的弹窗必定会笼罩后面的,成果如下

说到这里,我又想到了一些UI组件库里大到可怕的z-index,大概率就是通过计算得出的

四、焦点隔离个性

除了下面一些比拟直观的个性外,还有一些可能会疏忽的,比方焦点的管制。

默认状况下,关上弹窗后会主动聚焦到弹窗内的第一个可聚焦元素上

还能够有input输入框

<dialog>  <form method="dialog">    <h3>欢送关注前端侦探</h3>    <input name="txt">    <button>敞开</button>  </form></dialog>

关上弹窗后能够间接输出,无需额定操作,几乎不要太不便

留神,留神,留神:经测试发现,如果增加了关上动画,聚焦个性就会生效

当然,这些只是小儿科,一点点额定的 JS 也能解决,上面介绍一个零碎级别的焦点隔离个性。什么意思呢?就是说在关上弹窗后,弹窗就成了一个独立的载体,焦点只能在这个范畴内挪动,也就是说,无论tab键如何切换,焦点不会跑到弹窗里面去,上面是一个比照成果

  1. 一般弹窗成果

  1. 模态弹窗成果

这个成果其实是和新出的inert属性作用比拟相似的,然而要比inert呈现的更早,也能够说是通过inert属性将这种隔离个性通用化了,让平民老百姓也能够享受这种高级个性。有趣味的能够拜访我之前的这篇文章:疾速理解 inert 属性

五、顶层个性 top-layer

最初介绍一个即使是 JS 也无奈模仿的零碎级新个性,top-layer

不晓得大家有没有遇到这样的问题,有些弹窗因为业务须要,不得已写在了某些容器上面,即使是fixed定位,也会有生效的时候,比方上面这个例子,父容器如果有transform相干属性并且超出暗藏,就会呈现这样被裁剪的情景

下面这个例子来源于 xy-ui 中的 dialog 组件,后续优化,敬请期待~

在以前,或者说很多框架中,都会想方法把弹窗放到最外层的 body下,这样就不受影响了,比方上面是vue3中的解决形式

<div>  <Teleport to="body"> <!--将子内容传送到body下-->      <dialog></dialog>  </Teleport></div>

但当初,有了全新的 top-layer ,所有都好办了,比方上面是一个通过dialog.showModal()关上的弹窗

你会发现,尽管dialog依然在原来地位上,但真正渲染到了一个#top-layer的层级上,这个层级十分非凡,曾经超过了html文档流,能够说是独一档的存在,这样,无论的dialog在什么地位,最初渲染的中央其实都在#top-layer层级上,天然也不会被父容器裁剪被暗藏了,示意如下

是不是和古代框架有些许相似呢?上面是一个弹窗里嵌套另外一个弹窗

<dialog id="dialog1">  ...  <button type="button" >关上弹窗2</button>  <dialog id="dialog2">        ...  </dialog></dialog>

成果如下

其实这也是后关上的弹窗永远要高于之前弹窗的起因,#top-layer是动态创建的,只有关上的弹窗才会渲染到该层级之下。

另外,经测试发现,firefox 以及 safari 尽管在开发者工具上看不到#top-layer,然而dialog体现根本简直统一,应该是曾经成为了标准规范,日后能够放心使用。

六、dom 其实也是在一直倒退的

dialog其实我在两三年之前就有钻研过,那时还没有这么多新个性,也有可能是钻研不精,起初就搁置了,而后最近在我的项目中用了dialog,无心中又发现了很多有意思的新个性,这意味着,dom 其实也是在一直倒退的,有必要把以前曾经用过的再翻出来过一遍,说不定还能发现意想不到的后果,上面是要点总结

  1. dialog 的关上和敞开办法很蛊惑,别离是show() / close()
  2. dialog中表单元素在增加method=dialog属性之后,只有触发表单提交就会主动敞开弹窗,无需额定 js
  3. 通过showModal()能够关上模态弹窗,并且后关上的弹窗永远比先关上的弹窗层级要高,无需手动计算层级
  4. 关上弹窗会主动聚焦到弹窗内的第一个可聚焦元素,不便疾速输出
  5. 模态弹窗的焦点不会聚焦到弹窗内部,这和inert个性比拟相似
  6. 模态弹窗其实是渲染到了html文档流之外,一个叫#top-layer的层级上,因而不会受到原父容器的影响

很多同学往往过于关注 JavaScript和古代风行框架,而漠视了原生 dom 的倒退,但原生 dom 带来的很多新个性往往是零碎级别的,有可能你辛辛苦苦实现的一个性能,原生一个属性就搞定,而且成果更好,所以请不要忘了原生。最初,如果感觉还不错,对你有帮忙的话,欢送点赞、珍藏、转发❤❤❤

欢送关注我的公众号:前端侦探