(Vue.js) Scrolling in the modal will also scroll the back of the modal
Solution 1
Most modal packages solve this by applying a class to the <body>
tag when a modal is opened. For example, <body class="modal-open">
. Then in your application's CSS, you can add this rule:
body.modal-open {
overflow: hidden;
}
This will make it so that the page behind the modal is no longer scrollable.
Whichever modal package you are using likely fires events when the modal is opened or closed. You can apply this class to the <body>
tag in the open
event handler, and remove the class from the <body>
tag in the close
event handler.
UPDATE
Based on the code you added, here's how you can toggle the modal-open
class on the <body>
tag:
...
<div @click="showModal(item)" style="cursor:pointer;">
<img :src="item.thumbnail" />
</div>
<Modal v-if='item.show' @close="hideModal(item)">
<div slot='body'>
<img :src="item.thumbnail" :class="`img-index--${index}`"/>
</div>
</Modal>
...
{
...
methods: {
showModal(item) {
item.show = true
document.body.classList.add("modal-open");
},
hideModal(item) {
item.show = false;
document.body.classList.remove("modal-open");
}
},
...
}
See this jsFiddle for reference.
Solution 2
I can't see your specific code running, but you can generally fix this by setting the body of your page to "overflow:hidden" when you open your modal. To make it more elegant, check to see if the page has scrollbars and add some margin to the right side to prevent content shift. I've used this scrollbar detection in the past, but I'd strip it down to the bare minimum if I used it today... I no longer care about old IE.
Comments
-
ddon almost 2 years
Clicking on the image brings up a long, scrolling modal. The problem is that if you scrolling in the modal will also scroll the back of the modal. How do you solve it?
Modal is a component. Here is my code:
Carousel.vue
<template> <div> <div v-for="(item, index) in photos" :key="index"> <div @click="imgClick(item)" style="cursor:pointer;"> <img :src="item.thumbnail" /> </div> <Modal v-if='item.show' @close="item.show = false"> <div slot='body'> <img :src="item.thumbnail" :class="`img-index--${index}`"/> </div> </Modal> </div> </div> </template> <script> import Modal from './Modal.vue' export default { props: { items: { type: Array, default: () => [] } }, data() { return { photos: {} } }, created() { this.photos = this.items.map(item => { return { ...item, show: false } }) }, methods: { imgClick(item) { item.show = true } }, components: { Modal: Modal } } </script>