6

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>
ddon
  • 185
  • 3
  • 4
  • 15
  • This is probably a CSS issue and already has an answer here. https://stackoverflow.com/questions/9538868/prevent-body-from-scrolling-when-a-modal-is-opened – skribe Sep 25 '19 at 17:37
  • @skribe I didn't use a CSS library like Bootstrap. Thank you for your search. – ddon Sep 25 '19 at 17:45
  • @zoecode Take a look at my answer below, let me know if it helps. Cheers! – Vince Sep 26 '19 at 15:51
  • @zoecode if my answer was helpful to you, please upvote it & mark it as "accepted" so that it can help other users in the future. Thanks! – Vince Oct 02 '19 at 16:19
  • @Vince I don't know how to add class to . I also don't know how to add a class named "modal-open" only when the modal is open. I did not understand well. Sorry for the late response. – ddon Oct 02 '19 at 18:54
  • What package are you using for your modal? – Vince Oct 02 '19 at 18:57
  • 1
    @Vince When clicking on the image, the `v-if` conditional statement (` ... Modal>`) is used to pop up a component named 'Modal'. The configuration of Modal.vue is the same as the [link](https://vuejs.org/v2/examples/modal.html). Also I don't use bootstrap. – ddon Oct 02 '19 at 19:25
  • @zoecode Check the update to my answer. – Vince Oct 02 '19 at 19:47
  • @Vince I used only jQuery. So I'm not good at Vue. Thank you for your help despite the lack of explanation. Now that's what I wanted. – ddon Oct 03 '19 at 05:40
  • @zoecode No problem – glad I could help! – Vince Oct 03 '19 at 15:08

3 Answers3

7

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.

Vince
  • 3,207
  • 1
  • 17
  • 28
  • This works, but if the scrollbar affects layout (usually seen when using a non-touch mouse) it has a huge downside of the website resizing slightly wider so everything shifts. Preventing scrolling events somehow would be better. – Trevor Oct 13 '21 at 22:37
  • @Trevor That's a pretty rare corner-case that doesn't apply to the question that was asked and answered 2+ years ago... What browser are you using where this is an issue? Because it's not Chrome or Firefox. Their scrollbars do not affect page width. – Vince Oct 19 '21 at 21:57
  • Fair that it's a corner-case. I see it on macOS Big Sur using the latest versions of Chrome and FF. It depends on the type of mouse you're using. If you're using a touch mouse such as a track pad, Apple magic mouse, or mobile, scrollbars won't affect layout. But using a regular external mouse, scrollbars do take up horizontal/vertical space and will widen the layout of your site if you hide them. Check out https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/ for a solution that's similar to yours, but also accounts for reflow. – Trevor Oct 20 '21 at 22:20
1

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.

TimHayes
  • 3,684
  • 21
  • 26
0

You can temporarily disable events that cause scrolling.

How to disable scrolling temporarily?

Some solutions just disable scrolling by hiding the scrollbar (overflow: hidden; on the body element), but this solution has the benefit of the background content not shifting over if the scrollbar is styled to affect layout, which most browsers do if you're using a non-touch mouse.

Trevor
  • 263
  • 2
  • 11