我们应得的模态窗口

让我们开始吧


在不同的标准和质量清单中,有一个项目,例如在打开模式窗口时阻止页面滚动。 模态窗口仅意味着与之交互。

许多人会问一个问题:“为什么不使用现成的解决方案?”。 问题在于此功能要么根本没有实现,要么做得很差。 您可以使用最简单,最糟糕的解决方案:

.body { overflow: hidden;} 

在这里,我们会略微抽动页面。 代号 值得注意的是:仅在页面上滚动的位置才会发生此问题,例如,在Safari中不存在此类问题。

动画问题(Gif)


npm开放空间中的一些解决方案提供了以缩进或替换为滚动(样式简单的灰色条)的缩进或块来替代滚动的方法,这是很多魔术,但是它们不能解决问题。

我们将对初始代码进行一些调整,一切正常:

 .body { position:fixed; overflow-y: scroll; } 

现在出现了另一个问题:页面跳了起来。 代号 通过js的解决方案很简单:打开页面时,我们将页面滚动到的值设置为<body> Code标记的top属性。

 function getBodyScrollTop() { return self.pageYOffset || (document.documentElement && document.documentElement.ScrollTop) || (document.body && document.body.scrollTop); } openModalButton.addEventListener('click', e => { e.preventDefault() body.dataset.scrollY = getBodyScrollTop() //    body.style.top = `-${body.dataset.scrollY}px` modal.classList.add('modal--open') body.classList.add('body-lock') }) closeModalButton.addEventListener('click', e => { e.preventDefault() modal.classList.remove('modal--open') body.classList.remove('body-lock') window.scrollTo(0, body.dataset.scrollY) //  ,   }) 

有时,网站上的页面内容可能很少且没有滚动,但是当您打开模式窗口时,我们的代码会将其添加。 让我们稍微修改一下滚动条。 现成的解决方案

 function existVerticalScroll() { return document.body.offsetHeight > window.innerHeight } openModalButton.addEventListener('click', e => { e.preventDefault() body.dataset.scrollY = getBodyScrollTop() modal.classList.add('modal--open') if(existVerticalScroll()) { //   body.classList.add('body-lock') body.style.top = `-${body.dataset.scrollY}px` } }) closeModalButton.addEventListener('click', e => { e.preventDefault() modal.classList.remove('modal--open') if(existVerticalScroll()) { //   body.classList.remove('body-lock') window.scrollTo(0,body.dataset.scrollY) } }) 

有空


如果您不考虑这一点,则可以使用模态窗口外部的标签进行移动。 在gif上,只需几次Tab键

动画问题(Gif)


在Internet上,没有解决此问题的简单方法,并且在没有focus-trap.js库的情况下编写拐杖自行车不是很合理。 在这里,作者更详细地揭示了图书馆的主题及其问题

 //     const modalFocusTrap = createFocusTrap(".modal"); //      openModalButton.addEventListener('click', e => { e.preventDefault() body.dataset.scrollY = getBodyScrollTop() modal.classList.add('modal--open') modalFocusTrap.activate(); //  .   if(existVerticalScroll()) { body.classList.add('body-lock') body.style.top = `-${body.dataset.scrollY}px` } }) closeModalButton.addEventListener('click', e => { e.preventDefault() modal.classList.remove('modal--open') modalFocusTrap.deactivate(); //  .   if(existVerticalScroll()) { body.classList.remove('body-lock') window.scrollTo(0,body.dataset.scrollY) } }) 

总结


即使页面上有多个模式窗口,您也可以将所有代码包装在一个函数中,并传递模式窗口的类名。

 function initModal(className) { // ,        } initModal('modalName1') initModal('modalName2') 

乍一看,问题很简单,但是有很多不明显的时刻。 我认为本文将帮助您制作更好的模态窗口。 准备好的代码

有用的材料


Source: https://habr.com/ru/post/zh-CN483114/


All Articles