HTML`dialog`元素:独立于背景滚动内容

时间:2019-05-04 04:43:17

标签: html css scroll overflow

我正在尝试使用module.exports.setPoints = function (amnt, id) { db.run('UPDATE users SET points = ? WHERE id = ?', amnt, id); } 元素。

关闭对话框/模式时,主体应可滚动。

打开对话框/模式时,如果其内容较大,则对话框/模式应可滚动。

但是,当对话框/模式打开时,我不想将滚动应用于对话框/模式主体背景,这似乎是默认情况下所做的。 / p>

示例:https://output.jsbin.com/mutudop/3

当对话框/模式打开时,如何使滚动仅适用于对话框/模式的内容?

注意:我只对使用本机dialog元素的解决方案感兴趣。

4 个答案:

答案 0 :(得分:2)

所以我也尝试了一下,并提出了:

(function() {
  var openBtn = document.querySelector("button#open");
  var myDialog = document.querySelector("dialog");

  openBtn.addEventListener('click', function() {
    if (typeof myDialog.showModal === "function") {
      myDialog.showModal();
      document.querySelector("body").classList.add("overflow-hidden");
    } else {
      alert("Dialog API not supported by browser");
    }
  });
})();
* {
  box-sizing: border-box;
}

.wrapper {
  height: 10000px;
}

dialog {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  border: 0;
  z-index: 100;
  background: transparent;
  overflow-y: auto;
}

dialog>div {
  width: 50%;
  height: 500px;
  background: white;
  border: 3px solid black;
  margin: 0 auto;
  margin-top: 50px;
}

.overflow-hidden {
  overflow: hidden;
}
<div class="wrapper">
  <dialog>
    <div>
      <form method="dialog">
        <button onclick='document.body.classList.remove("overflow-hidden");' value="cancel">Cancel</button>
      </form>
    </div>
  </dialog>

  <button id="open">Open Dialog</button>
  <h4>You can scroll the body now but not when the dialog is opened.</h4>
</div>

您可能已经注意到,我添加了两行JS来隐藏/显示overflow的{​​{1}},由于您可能无法定位body,因此您可能会需要它们纯CSS,如果您想检查body是否打开。

如果您想要它们,您可以将其删除,即可正常使用。但是,您将在右侧有两个滚动条。这是没有JS的外观:

dialog
(function() {
  var openBtn = document.querySelector("button#open");
  var myDialog = document.querySelector("dialog");

  openBtn.addEventListener('click', function() {
    if (typeof myDialog.showModal === "function") {
      myDialog.showModal();
    } else {
      alert("Dialog API not supported by browser");
    }
  });
})();
* {
  box-sizing: border-box;
}

.wrapper {
  height: 10000px;
}

dialog {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  border: 0;
  z-index: 100;
  background: transparent;
  overflow-y: auto;
}

dialog>div {
  width: 50%;
  height: 500px;
  background: white;
  border: 3px solid black;
  margin: 0 auto;
  margin-top: 50px;
}

.overflow-hidden {
  overflow: hidden;
}

如果您需要任何解释,请告诉我,但我认为代码应该是不言自明的。

答案 1 :(得分:0)

简单的解决方案是:一旦显示了mnodel,再做一个DIV作为覆盖全屏的叠加层,然后在该位置放css {pointer-events:none},然后将模型放在顶部。用户不能单击模型数据以外的身体内容。

我已创建示例:http://jsfiddle.net/z3sgvnox/

<body id="content-body">


<div id="container">
  <dialog id="my-dialog">
    <div id="my-dialog__content">
      <form method="dialog">
        <menu>
          <button id="cancel-button" value="cancel">Cancel</button>
        </menu>
      </form>
    </div>
  </dialog>

  <menu>
    <button id="open-dialog">Open Dialog</button>
  </menu>
</div>
</body>

CSS

#container {
  height: 100vh;
  width: 100vw;
  position: fixed;
  top: 0;
  left: 0;
  background: #ccc;
}

#my-dialog {
  margin-top: 1rem;
  margin-bottom: 3rem;
  width: 50%;
  overflow-y: auto;
      max-height: 80%;
}
.hideScroll{
  overflow:hidden;
  pointer-events:none;
}

#my-dialog__content {
  display: flex;
  flex-direction: column;
  height: 200vh;
}

menu {
  width: 100%;
  padding: 0;
  margin: 0 auto;
}

#cancel-button {
  width: 100%
}

JS:

(function() {
  var openBtn = document.getElementById('open-dialog');
  var myDialog = document.getElementById('my-dialog');
var bodyData = document.getElementById('content-body');
  openBtn.addEventListener('click', function() {
    if (typeof myDialog.showModal === "function") {
      myDialog.showModal();
      bodyData.classList.add("hideScroll");
    } else {
      alert("Dialog API not supported by browser");
    }
  });

})();

答案 2 :(得分:0)

这个答案考虑了转义键。我将 keydown 事件侦听器添加到 document.documentElement 而不是实际的 dialog 元素。这是因为当 dialog 具有 keydown 事件侦听器时,它并不总是会触发。例如,如果 dialog 处于打开状态并且其中的一个按钮具有焦点并且您按下退出键,则 keydown 事件侦听器触发。但让我们假设 dialog 中有一些文本,您突出显示该文本,然后按 Esc 键。在这种情况下,keydown 事件侦听器将触发。

const activeModals = [];

function openModal(dialogSelector) {
  const dialog = document.querySelector(dialogSelector);
  dialog.showModal();
  activeModals.push(dialog);
  document.body.classList.add('overflow-hidden');
}

function closeActiveModal() {
  const activeModal = activeModals.pop();
  activeModal.close();

  if (activeModals.length === 0) {
    document.body.classList.remove('overflow-hidden');
  }
}

document.documentElement.addEventListener('keydown', (e) => {
  if (e.key === 'Escape' && activeModals.length) {
    e.preventDefault();
    closeActiveModal();
  }
});

document.querySelectorAll('[data-toggle="modal"]').forEach((button) => {
  button.addEventListener('click', () => {
    openModal(button.getAttribute('data-target'));
  });
});

document.querySelectorAll('[data-dismiss="modal"]').forEach((button) => {
  button.addEventListener('click', closeActiveModal);
});

let fillerHtml = '';

for (let i = 1; i <= 100; i++) {
  fillerHtml += `<p>${i}</p>`;
}

document.querySelectorAll('.filler').forEach((div) => {
  div.innerHTML = fillerHtml;
});
.overflow-hidden {
  overflow: hidden;
}

p {
  font-size: 20px;
}
<button data-toggle="modal" data-target="#dialog1">Open Dialog 1</button>

<dialog id="dialog1">
  <h1>Dialog 1</h1>
  <button data-dismiss="modal">Close Dialog 1</button>
  <button data-toggle="modal" data-target="#dialog2">Open Dialog 2</button>
  <div class="filler"></div>
</dialog>

<dialog id="dialog2">
  <h1>Dialog 2</h1>
  <button data-dismiss="modal">Close Dialog 2</button>
</dialog>

<div class="filler"></div>

答案 3 :(得分:-1)

更新

我创建了另一个示例,如果您的主要内容大于主要内容,则主要内容不会与您的模式一起滚动。您可以在容器上将position设置为fixed

(function() {
  var openBtn = document.getElementById('open-dialog');
  var myDialog = document.getElementById('my-dialog');

  openBtn.addEventListener('click', function() {
    if (typeof myDialog.showModal === "function") {
      myDialog.showModal();
    } else {
      alert("Dialog API not supported by browser");
    }
  });

})();
#container {
  height: 100vh;
  width: 100vw;
  position: fixed;
  top: 0;
  left: 0;
  background: #ccc;
}

#my-dialog {
  margin-top: 1rem;
  margin-bottom: 3rem;
  top: 3rem;
  width: 50%;
  overflow-y: auto;
}

#my-dialog__content {
  display: flex;
  flex-direction: column;
  height: 200vh;
}

menu {
  width: 100%;
  padding: 0;
  margin: 0 auto;
}

#cancel-button {
  width: 100%
}
<div id="container">
  <dialog id="my-dialog">
    <div id="my-dialog__content">
      <form method="dialog">
        <menu>
          <button id="cancel-button" value="cancel">Cancel</button>
        </menu>
      </form>
    </div>
  </dialog>

  <menu>
    <button id="open-dialog">Open Dialog</button>
  </menu>
</div>

原始答案

您可以在对话框上设置max-height并相应地设置对话框内容的样式。参见下面的示例。

(function() {
  var openBtn = document.getElementById('open-dialog');
  var myDialog = document.getElementById('my-dialog');

  openBtn.addEventListener('click', function() {
    if (typeof myDialog.showModal === "function") {
      myDialog.showModal();
    } else {
      alert("Dialog API not supported by browser");
    }
  });

})();
#my-dialog {
  width: 50%;
  max-height: 50vh;
  overflow-y: auto;
}

#my-dialog__content {
  display: flex;
  flex-direction: column;
  height: 150vh;
}

menu {
  width: 100%;
  padding: 0;
  margin: 0 auto;
}

#cancel-button {
  width: 100%
}
<div id="container">
  <dialog id="my-dialog">
    <div id="my-dialog__content">
      <form method="dialog">
        <menu>
          <button id="cancel-button" value="cancel">Cancel</button>
        </menu>
      </form>
    </div>
  </dialog>

  <menu>
    <button id="open-dialog">Open Dialog</button>
  </menu>
</div>